using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;
using Microsoft.Win32;
using System.IO;
using System.ComponentModel;
using System.Windows.Threading;
using System.Windows;
using AForge.Video.DirectShow;
using TwoCamWPF.Helpers;

namespace TwoCamWPF.Settings
{



    class ClassSettings : Dictionary<string, ISubSettings>, ISubSettings
    {
      //  Dictionary<string, ISubSettings> subsetings = new Dictionary<string, ISubSettings>();
        //public ISubSettings this[string index]
        //{
        //    get
        //    {
        //        return subsetings[index];
        //    }
        //    set
        //    {
        //        subsetings[index] = value;
        //    }
        //}
     
        static readonly string FileName = "./settings.xml";

        public ClassSettings()
        {
            CamerasSettings = new CamerasSettings();
            Add("CamerasSettings", CamerasSettings);
            StartSettings = new StartSettings();
            Add("StartSettings", StartSettings);
            RecordSettings = new RecordSettings();
            Add("RecordSettings", RecordSettings);
        }
        public CamerasSettings CamerasSettings;
        public StartSettings StartSettings;
        public RecordSettings RecordSettings;
 


        public static ClassSettings LoadSettings()
        {
            Log.LogClass.Enqueue(MethodBase.GetCurrentMethod(), "Загрузка настроек");
            ClassSettings settings = new ClassSettings();
            XmlDocument doc = new XmlDocument();
            try
            {
                doc.Load(FileName);
            }
            catch (Exception e)
            {
                Log.LogClass.Enqueue(MethodBase.GetCurrentMethod(), "Ошибка загрузки параметров в главной процедуре ");
                Log.LogClass.Enqueue(MethodBase.GetCurrentMethod(), e.Message);
                return settings;
            }
            settings.Load(doc.DocumentElement);
            
            return settings;
        }

        public void SaveSettings()
        {
            Log.LogClass.Enqueue(MethodBase.GetCurrentMethod(), "Сохранение настроек");
              
            XmlWriterSettings settings = new XmlWriterSettings();

            // включаем отступ для элементов XML документа
            // (позволяет наглядно изобразить иерархию XML документа)
            settings.Indent = true;
            settings.IndentChars = "    "; // задаем отступ, здесь у меня 4 пробела
            // задаем переход на новую строку
            settings.NewLineChars = "\n";

            // Нужно ли опустить строку декларации формата XML документа
            // речь идет о строке вида "<?xml version="1.0" encoding="utf-8"?>"
            settings.OmitXmlDeclaration = true;
            XmlWriter output = null;
            try
            {
                output= XmlWriter.Create(FileName, settings);
                Write(output);
                output.Flush();
            }
            catch (Exception e)
            {
                Log.LogClass.Enqueue(MethodBase.GetCurrentMethod(), "Ошибка сохранения параметров в главной процедуре ");
                Log.LogClass.Enqueue(MethodBase.GetCurrentMethod(), e.Message);
            }
            finally
            {
                if (output != null)
                    output.Close();
            }
        }

        public void LockForChange() {
            Log.LogClass.Enqueue(MethodBase.GetCurrentMethod(), "Начало создания настроек");
            if (OnLocked != null)
                OnLocked(this);
        }

        public void Unlock()
        {
            Log.LogClass.Enqueue(MethodBase.GetCurrentMethod(), "Создание настроек завершено");
            if (OnLoaded != null)
                OnLoaded(this);
        }

        public event Action<ClassSettings> OnLoaded;
        public event Action<ClassSettings> OnLocked;

        public void ReloadCamList() {
            VideoDeviceWatcher.ReloadCamList();
            //Загружаем настройки

            foreach (VideoDeviceWatcher watcher in VideoDeviceWatcher.watchers) {
                OneCameraSettings s =  (this["CamerasSettings"] as CamerasSettings).FirstOrDefault(p => p.MonikerString == watcher.MonikerString);
                if (s == null)
                {
                    s = new OneCameraSettings(watcher);
                    (this["CamerasSettings"] as CamerasSettings).Add(s);
                }
                else
                {
                    if (s.device == null)
                        s.AssignDevice(watcher);
                }
            }
        }

        public void Load(XmlNode node)
        {
            foreach (XmlNode child in node.ChildNodes)
            {
                ISubSettings set = this.FirstOrDefault(p => p.Key == child.Name).Value;
                if (set == null)
                    continue;
                set.Load(child);
            }
        }

        public void Write(XmlWriter output)
        {
            output.WriteStartElement("Settings", "");
            this.ForEach(p => p.Value.Write(output));
            output.WriteEndElement();
        }


        public void Save()
        {
            this.LockForChange();
            if (OnSave != null)
                OnSave(this);
            this.ForEach(p => p.Value.Save());
            this.Unlock();
            this.SaveSettings();

        }

        public event Action<ISubSettings> OnSave;
    }




}
