using log4net;
using Org.BouncyCastle.Tsp;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Xml;
using TSManagementApp.Properties;
using TSManagementApp.Utils;

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

        private SettingsModel _settings;

        public SettingsManager()
        {
            _settings = new SettingsModel();
            InitCollections();
        }

        public SettingsModel Settings
        {
            get { return _settings; }
            set { _settings = value; }
        }

        public ObservableCollection<ShaAlgorithmType> TsaShaAlogirthms { get; set; }
        public ObservableCollection<TimeStampServerModel> TsaTimeStampServers { get; set; }

        private void InitCollections()
        {
            TsaShaAlogirthms = new ObservableCollection<ShaAlgorithmType>
            {
                new ShaAlgorithmType(Resources.ShaAlgorithmDescription_Sha1, TspAlgorithms.Sha1),
                new ShaAlgorithmType(Resources.ShaAlgorithmDescription_Sha256, TspAlgorithms.Sha256),
                new ShaAlgorithmType(Resources.ShaAlgorithmDescription_Sha512, TspAlgorithms.Sha512)
            };

            TsaTimeStampServers = new ObservableCollection<TimeStampServerModel>(); //TODO - při přidání anglické verze poměnit
            // do .ini souborů přidáme anglický překlad hned za českou verzi (oddělené čárkou) a až pak url adresu. Legth se změni na tři,
            // a trochu se pohraje s vytvořením objektu
            if (File.Exists($"{SystemUtils.AssemblyDirectory}\\Files\\TSA_urls.ini"))
            {
                string[] tsaServersLines = File.ReadAllLines($"{SystemUtils.AssemblyDirectory}\\Files\\TSA_urls.ini");
                foreach (string tsaServer in tsaServersLines)
                {
                    string[] s = tsaServer.Split(',');
                    if (s.Length == 2)
                        TsaTimeStampServers.Add(new TimeStampServerModel(s[0], s[1]));
                }
            }
        }

        public void SetGeneralSettings(bool ieSettingsIsChecked, bool proxyIsChecked, string proxyServer, 
            string UserName, string password, bool automaticUpdateIsChecked)
        {
            _settings.GeneralSettings.IeSettingsIsChecked = ieSettingsIsChecked;
            _settings.GeneralSettings.ProxyIsChecked = proxyIsChecked;
            _settings.GeneralSettings.ProxyServer = proxyServer;
            _settings.GeneralSettings.UserName = UserName;
            _settings.GeneralSettings.Password = password;
            _settings.GeneralSettings.AutomaticUpdateIsChecked = automaticUpdateIsChecked;
            string logMessage = null;
            if (ieSettingsIsChecked)
                logMessage += "Internet connection = Internet Explorer settings";
            else if (proxyIsChecked)
                logMessage += "Internet connection = using proxy server";

            logMessage += $"; Username for proxy server = {UserName}; Password for proxy server = {password}";
            logMessage += $"; Automatic updates set to = {automaticUpdateIsChecked.ToString()}";
            log.Info($"General settings set to: {logMessage}");
        }

        public void SetTsaSettings(bool tsaAuthCertIsChecked, bool tsaIpIsChecked, bool tsaAuthLoginDataIsChecked, X509Certificate2 tsaAuthCert,
            string tsaLoginName, string tsaLoginPassword, string tsaPolitics, string selectedMessageImprintType, string tsaSelectedTimeStampServer, bool noAuthIsChecked)
        {
            _settings.TsaSettings.NoAuthIsChecked = noAuthIsChecked;
            _settings.TsaSettings.AuthCertIsChecked = tsaAuthCertIsChecked;
            _settings.TsaSettings.AuthIpIsChecked = tsaIpIsChecked;
            _settings.TsaSettings.AuthLoginDataIsChecked = tsaAuthLoginDataIsChecked;
            _settings.TsaSettings.AuthCert = tsaAuthCert;
            _settings.TsaSettings.LoginName = tsaLoginName;
            _settings.TsaSettings.LoginPassword = tsaLoginPassword;
            _settings.TsaSettings.Politics = tsaPolitics;
            _settings.TsaSettings.MessageImprintType = selectedMessageImprintType;
            _settings.TsaSettings.SelectedTimeStampServer = tsaSelectedTimeStampServer;

            string logMessage = null;
            if (tsaAuthCertIsChecked)
                logMessage += "Tsa authentication - certificate";
            else if (tsaAuthLoginDataIsChecked)
                logMessage += "Tsa authentication - login data";
            else if (tsaIpIsChecked)
                logMessage += "Tsa authentication - anonymous using IP";
            if (tsaAuthCert != null)
                logMessage += $"; Auth cert set to {tsaAuthCert.Subject}";
            logMessage += $"; Login data for tsa - {tsaLoginName}:{tsaLoginPassword}; TSA politics - {tsaPolitics}; Selected hash alg - {selectedMessageImprintType}";

            if (tsaSelectedTimeStampServer != null)
                logMessage += $"; Selected time stamp server - {tsaSelectedTimeStampServer}";

            log.Info($"TSA settings set to - {logMessage}");
        }

        public void SerializeSettings()
        {
            try
            {
                log.Info("Start serializing settings");
                XmlDocument xml = new XmlDocument();
                xml.AppendChild(xml.CreateXmlDeclaration("1.0", "utf-8", null));
                XmlNode settings = xml.CreateElement("TSManagementAppSettings");

                XmlNode generalSettings = xml.CreateElement("GeneralSettings");
                XmlNode node = xml.CreateElement("IeSettingsIsChecked");
                node.InnerText = _settings.GeneralSettings.IeSettingsIsChecked.ToString();
                generalSettings.AppendChild(node);
                node = xml.CreateElement("ProxyIsChecked");
                node.InnerText = _settings.GeneralSettings.ProxyIsChecked.ToString();
                generalSettings.AppendChild(node);
                node = xml.CreateElement("ProxyServer");
                node.InnerText = _settings.GeneralSettings.ProxyServer;
                generalSettings.AppendChild(node);
                node = xml.CreateElement("UserName");
                node.InnerText = _settings.GeneralSettings.UserName;
                generalSettings.AppendChild(node);
                node = xml.CreateElement("Password");
                if(_settings.GeneralSettings.Password != null)
                    node.InnerText = Convert.ToBase64String(Encoding.UTF8.GetBytes(_settings.GeneralSettings.Password));
                generalSettings.AppendChild(node);
                settings.AppendChild(generalSettings);

                XmlNode tsaSettings = xml.CreateElement("TsaSettings");
                node = xml.CreateElement("NoAuthIsChecked");
                node.InnerText = _settings.TsaSettings.NoAuthIsChecked.ToString();
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaAuthCertIsChecked");
                node.InnerText = _settings.TsaSettings.AuthCertIsChecked.ToString();
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaAuthIpIsChecked");
                node.InnerText = _settings.TsaSettings.AuthIpIsChecked.ToString();
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaAuthLoginDataIsChecked");
                node.InnerText = _settings.TsaSettings.AuthLoginDataIsChecked.ToString();
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaAuthCert");
                if (_settings.TsaSettings.AuthCert != null)
                    node.InnerText = Convert.ToBase64String(_settings.TsaSettings.AuthCert.RawData);
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaLoginName");
                node.InnerText = _settings.TsaSettings.LoginName;
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaLoginPassword");
                if (_settings.TsaSettings.LoginPassword != null)
                    node.InnerText = Convert.ToBase64String(Encoding.UTF8.GetBytes(_settings.TsaSettings.LoginPassword));
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaPolitics");
                node.InnerText = _settings.TsaSettings.Politics;
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaMessageImprintType");
                node.InnerText = _settings.TsaSettings.MessageImprintType;
                tsaSettings.AppendChild(node);
                node = xml.CreateElement("TsaSelectedTimeStampServer");
                    node.InnerText = _settings.TsaSettings.SelectedTimeStampServer;
                tsaSettings.AppendChild(node);
                settings.AppendChild(tsaSettings);

                xml.AppendChild(settings);

                xml.Save($"{SystemUtils.UserLocalAppDirectory}\\TSManagementAppSettings.xml");

                log.Info("Settings data successfully serialized");
            }
            catch (Exception ex)
            {
                log.Error($"Settings serialization failed - {ex.ToString()}");
            }
        }
    }
}
