using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;

namespace RecrownedGTK.Persistence
{
    /// <summary>
    /// Manages a bundle of preferences.
    /// </summary>
    public class PreferencesManager
    {
        private readonly Dictionary<Type, object> preferenceList;
        string savePath;
        XmlSerializer xmlSerializer;

        /// <summary>
        /// Constructs the preference manager.
        /// </summary>
        /// <param name="savePath">The path of the directory in which the preferences should be saved.</param>
        /// <param name="preferences">The preferences to be serialized and unserialized in XML format.</param>
        public PreferencesManager(string savePath, params object[] preferences)
        {
            this.savePath = savePath;
            Directory.CreateDirectory(savePath);
            preferenceList = new Dictionary<Type, object>();
            Debug.WriteLine("Preference manager setting up...");
            Type[] preferenceTypes = new Type[preferences.Length];
            for (int prefID = 0; prefID < preferences.Length; prefID++)
            {
                preferenceList.Add(preferences[prefID].GetType(), preferences[prefID]);
                preferenceTypes[prefID] = preferences[prefID].GetType();
                Debug.WriteLine(preferences[prefID] + " added to list of preferences");
            }

            xmlSerializer = new XmlSerializer(typeof(object), preferenceTypes);
        }

        /// <summary>
        /// Returns the preference by type.
        /// </summary>
        /// <typeparam name="T">The preference needed.</typeparam>
        /// <returns>The preference needed.</returns>
        public T GetPreferences<T>()
        {
            return (T)preferenceList[typeof(T)];
        }

        /// <summary>
        /// Loads preferences.
        /// </summary>
        public void Load()
        {
            List<Type> keys = new List<Type>(preferenceList.Keys);

            foreach (Type key in keys)
            {
                if (!LoadSpecific(key))
                {
                    SaveSpecific(key);
                }
            }
        }

        /// <summary>
        /// Saves preferences.
        /// </summary>
        public void Save()
        {
            foreach (KeyValuePair<Type, object> prefs in preferenceList)
            {
                SaveSpecific(prefs.Key);
            }
        }

        private bool LoadSpecific(Type preference)
        {
            string path = savePath + "/" + preference.Name + ".xml";
            try
            {
                if (File.Exists(path))
                {
                    Stream stream = new FileStream(path, FileMode.Open);
                    preferenceList[preference] = xmlSerializer.Deserialize(stream);
                    stream.Close();
                    return true;
                }
            } catch (InvalidOperationException)
            {
            return false;
            }
            return false;
        }

        private void SaveSpecific(Type preference)
        {
            Stream stream = new FileStream(savePath + "/" + preference.Name + ".xml", FileMode.Create);
            xmlSerializer.Serialize(stream, preferenceList[preference]);
            stream.Close();
        }
    }
}