using log4net;
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Xml;
using TSManagementApp.Utils;

namespace TSManagementApp.Models
{
    public sealed class Manager
    {
        #region Logger
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        #endregion

       
        private static object _syncRoot = new Object();

        private Manager()
        {
            SettingsManager = new SettingsManager();

            Manager temp = LoadProfile();
            if(temp == null)
            {
                SettingsManager = new SettingsManager();
                TimeStampsManager = new TimeStampsManager();
            }
            else
            {
                SettingsManager = temp.SettingsManager ?? new SettingsManager();
                TimeStampsManager = temp.TimeStampsManager ?? new TimeStampsManager();
            }
        }
        private Manager(bool forDeserialize)
        {
            this.SettingsManager = new SettingsManager();
        }


        #region Properties

        private static volatile Manager _instance;
        public static Manager Instance
        {
            get
            {
                if(_instance == null)
                {
                    lock(_syncRoot)
                    {
                        _instance = new Manager();
                    }
                }
                return _instance;
            }
        }

        public SettingsManager SettingsManager { get; set; }
        public TimeStampsManager TimeStampsManager { get; set; }

        #endregion

        #region Methods

        private Manager LoadProfile()
        {
            try
            {
                Manager man = new Manager(true);
                man.SettingsManager = DeserializeSettings();
                man.TimeStampsManager = DeserializeTimeStampsHistory();

                return man;
            }
            catch (Exception ex)
            {
                log.Error($"Error while icializing manager - {ex.ToString()}");
                return null;
            }
        }

        // prázdná metoda použita jen proto aby sa mně vytvořila instance manageru při spuštění aplikace
        public void GetInstance()
        {
            log.Debug("Manager instance created");
        }

        private SettingsManager DeserializeSettings()
        {
            try
            {
                if (File.Exists($"{SystemUtils.UserLocalAppDirectory}\\TSManagementAppSettings.xml"))
                {
                    SettingsModel settings = new SettingsModel();
                    XmlDocument xml = new XmlDocument();
                    xml.Load($"{SystemUtils.UserLocalAppDirectory}\\TSManagementAppSettings.xml");

                    XmlNode generalSettings = xml.SelectSingleNode("/TSManagementAppSettings/GeneralSettings");
                    foreach (XmlNode node in generalSettings.ChildNodes)
                    {
                        switch (node.Name)
                        {
                            case "IeSettingsIsChecked":
                                settings.GeneralSettings.IeSettingsIsChecked = node.InnerText == "True" ? true : false; break;
                            case "ProxyIsChecked":
                                settings.GeneralSettings.ProxyIsChecked = node.InnerText == "True" ? true : false; break;
                            case "ProxyServer":
                                settings.GeneralSettings.ProxyServer = node.InnerText; break;
                            case "UserName":
                                settings.GeneralSettings.UserName = node.InnerText; break;
                            case "Password":
                                if (!string.IsNullOrWhiteSpace(node.InnerText))
                                    settings.GeneralSettings.Password = Encoding.UTF8.GetString(Convert.FromBase64String(node.InnerText)); break;
                            default: break;
                        }
                    }
                    XmlNode tsaSettings = xml.SelectSingleNode("/TSManagementAppSettings/TsaSettings");
                    foreach (XmlNode node in tsaSettings.ChildNodes)
                    {
                        switch (node.Name)
                        {
                            case "NoAuthIsChecked":

                            case "TsaAuthCertIsChecked":
                                settings.TsaSettings.AuthCertIsChecked = node.InnerText == "True" ? true : false; break;
                            case "TsaAuthIpIsChecked":
                                settings.TsaSettings.AuthIpIsChecked = node.InnerText == "True" ? true : false; break;
                            case "TsaAuthLoginDataIsChecked":
                                settings.TsaSettings.AuthLoginDataIsChecked = node.InnerText == "True" ? true : false; break;
                            case "TsaAuthCert":
                                if (!string.IsNullOrWhiteSpace(node.InnerText))
                                    settings.TsaSettings.AuthCert = new X509Certificate2(Convert.FromBase64String(node.InnerText));
                                break;
                            case "TsaLoginName":
                                settings.TsaSettings.LoginName = node.InnerText; break;
                            case "TsaLoginPassword":
                                if (!string.IsNullOrWhiteSpace(node.InnerText))
                                    settings.TsaSettings.LoginPassword = Encoding.UTF8.GetString(Convert.FromBase64String(node.InnerText)); break;
                            case "TsaPolitics":
                                settings.TsaSettings.Politics = node.InnerText; break;
                            case "TsaSelectedTimeStampServer":
                                settings.TsaSettings.SelectedTimeStampServer = node.InnerText; break;
                            case "TsaMessageImprintType":
                                settings.TsaSettings.MessageImprintType = node.InnerText; break;
                            default: break;
                        }
                    }

                    SettingsManager setMan = new SettingsManager();
                    setMan.Settings = settings;

                    return setMan;
                }
                else
                    return null;
            }
            catch(Exception ex)
            {
                log.Error($"Error while deserializing settings data - {ex.ToString()}");
                return null;
            }
        }

        private TimeStampsManager DeserializeTimeStampsHistory()
        {
            try
            {
                if (File.Exists($"{SystemUtils.UserLocalAppDirectory}\\TimeStampsHistory.xml"))
                {
                    TimeStampsManager tsMan = new TimeStampsManager();
                    XmlDocument xml = new XmlDocument();
                    xml.Load($"{SystemUtils.UserLocalAppDirectory}\\TimeStampsHistory.xml");
                    XmlNode timeStamps = xml.SelectSingleNode("/TimeStamps");
                    foreach (XmlNode timeStamp in timeStamps.ChildNodes)
                    {
                        TimeStampReqRes stamp = new TimeStampReqRes();
                        foreach (XmlNode node in timeStamp.ChildNodes)
                        {
                            switch (node.Name)
                            {
                                case "SourceFilePath":
                                    stamp.SourceFilePath = node.InnerText; break;
                                case "GenTime":
                                    stamp.GenTime = node.InnerText; break;
                                case "TimeStampFilePath":
                                    stamp.TimeStampFilePath = node.InnerText; break;
                                case "TimeStampFileName":
                                    stamp.TimeStampFileName = node.InnerText; break;
                                case "TimeStampFileType":
                                    stamp.TimeStampFileType = node.InnerText; break;
                                case "TimeStampRequest":
                                    if (!string.IsNullOrWhiteSpace(node.InnerText))
                                        stamp.TimeStampRequest = Convert.FromBase64String(node.InnerText);
                                    else
                                        stamp.TimeStampRequest = null;
                                    break;
                                case "TimeStampResponse":
                                    if (!string.IsNullOrWhiteSpace(node.InnerText))
                                        stamp.TimeStampResponse = Convert.FromBase64String(node.InnerText);
                                    else
                                        stamp.TimeStampResponse = null;
                                    break;
                                default: break;
                            }
                        }
                        tsMan.AddTimeStamp(stamp);
                    }
                    return tsMan;
                }
                else
                    return null;
            }
            catch (Exception ex)
            {
                log.Error($"Error while deserializing time stamp history - {ex.ToString()}");
                return null;
            }
        }

        #endregion
    }
}
