using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using Hiperscan.AnalysisModule.Identification;
using Hiperscan.ApoIdentCommon.ApoConfig.Enums;
using static Hiperscan.Common.I18n.CatalogLocale;

namespace Hiperscan.ApoIdentCommon.ApoConfig
{
    public abstract class RemoteSettings : SettingsTemplate<RemoteSettings>
    {
        public static readonly string URL_TAG = "Url";
        public static readonly string TCP_PORT_TAG = "Tcp";

        public static readonly string ARCHIVE_DOKU_TAG = "ArchiveDocu";
        public static readonly string REMEMBER_UPDATE_INFO_TAG = "RememberUpdateInfo";
        public static readonly string LOCALE_TAG = "Location";
        public static readonly string TEST_VERSION_TAG = "TestVersion";
        public static readonly string UPDATE_VALIDATION_DOCU_TAG = "UpdateValidationDocu";
        public static readonly string UPDATE_OTHER_PDFS_TAG = "UpdateSubstancePdfs";
        public static readonly string UPDATE_CERTIFICATE_TAG = "UpdateCertificate";
        public static readonly string UPDATE_IM_LICENSE_TAG = "UpdateIMLicenseText";
        public static readonly string UPDATE_ADDITIONAL_TESTS_PDFS_TAG = "UpdateAdditionalTestsPdfs";
        public static readonly string VALIDATED_CLASSIFIER_TAG = "ValidatedClassifier";
        public static readonly string ADDITIONAL_TESTED_CLASSIFIER_TAG = "AdditionalTestedClassifier";
        public static readonly string MANAGED_CLASSIFIER_TAG = "ManagedClassifier";
        public static readonly string IS_APO_IDENT_2_1_TAG = "IsApoIdent_2_1";
        public static readonly string INSTALL_DATE_TAG = "InstallDate";


        public RemoteSettings() : base()
        {
        }

        public RemoteSettings(XmlNode parent_node) : base(parent_node)
        {
        }

        public void Reset()
        {
            this.Init();
        }

        protected override void Init(XmlNode parent_node = null)
        {
            this.ModuleLocation = RemoteModuleLocationTypes.Local;
            this.Url = String.Empty;
            this.TcpPort = -1;
            this.ModuleVersion = String.Empty;
            this.ServerSuffix = String.Empty;
            this.Locale =LocaleType.Unknown;
            this.ReleaseExpirationTime = DateTime.MaxValue;
            this.UpdateValidationPdfs = false;
            this.UpdateSubstancePdfs = false;
            this.UpdateUpdateCertificate = false;
            this.UpdateAdditionalTestsPdfs = false;
            this.UpdateLicenceText = false;
            this.ValidatedModels = new List<string>();
            this.AdditionalTestedModels = new List<string>();
            this.TestVersion = null;
            this.ManagedModels = new List<string>();
            this.IsApoIdent_2_1 = false;
            this.InstallDate = DateTime.MaxValue;

            base.Init(parent_node);
        }

        protected override void Read(XmlNode parent_node)
        {
            try
            {
                XmlNode url_node = parent_node.SelectNodes(RemoteSettings.URL_TAG)[0];
                this.Url = url_node.InnerText;
            }
            catch (Exception) { }

            try
            {
                XmlNode port_node = parent_node.SelectNodes(RemoteSettings.TCP_PORT_TAG)[0];
                this.TcpPort = Int32.Parse(port_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNode location_node = parent_node.SelectNodes(RemoteSettings.LOCALE_TAG)[0];
                this.Locale = (LocaleType)Enum.Parse(typeof(LocaleType), location_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNode remember_node = parent_node.SelectNodes(RemoteSettings.REMEMBER_UPDATE_INFO_TAG)[0];
                this.ReleaseExpirationTime = DateTime.Parse(remember_node.InnerText, CultureInfo.InvariantCulture);
            }
            catch (Exception) { }

            try
            {
                XmlNode update_validation_node = parent_node.SelectNodes(RemoteSettings.UPDATE_VALIDATION_DOCU_TAG)[0];
                this.UpdateValidationPdfs = Boolean.Parse(update_validation_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNode update_substance_pdfs_node = parent_node.SelectNodes(RemoteSettings.UPDATE_OTHER_PDFS_TAG)[0];
                this.UpdateSubstancePdfs = Boolean.Parse(update_substance_pdfs_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNode update_certificate_node = parent_node.SelectNodes(RemoteSettings.UPDATE_CERTIFICATE_TAG)[0];
                this.UpdateUpdateCertificate = Boolean.Parse(update_certificate_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNode update_im_license_node = parent_node.SelectNodes(RemoteSettings.UPDATE_IM_LICENSE_TAG)[0];
                this.UpdateLicenceText = Boolean.Parse(update_im_license_node.InnerText);
            }
            catch (Exception)
            {
                this.UpdateLicenceText = true;
            }

            try
            {
                XmlNode update_additional_tests_node = parent_node.SelectNodes(RemoteSettings.UPDATE_ADDITIONAL_TESTS_PDFS_TAG)[0];
                this.UpdateAdditionalTestsPdfs = Boolean.Parse(update_additional_tests_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNodeList validated_classifier_nodes = parent_node.SelectNodes(RemoteSettings.VALIDATED_CLASSIFIER_TAG);
                foreach (XmlNode validated_clasiifier_node in validated_classifier_nodes)
                    this.ValidatedModels.Add(validated_clasiifier_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNodeList additional_tested_classifier_nodes = parent_node.SelectNodes(RemoteSettings.VALIDATED_CLASSIFIER_TAG);
                foreach (XmlNode additional_tested_clasiifier_node in additional_tested_classifier_nodes)
                    this.AdditionalTestedModels.Add(additional_tested_clasiifier_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNodeList test_version_nodes = parent_node.SelectNodes(RemoteSettings.TEST_VERSION_TAG);
                foreach (XmlNode test_version_node in test_version_nodes)
                    this.TestVersion = Boolean.Parse(test_version_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNodeList managed_classifier_nodes = parent_node.SelectNodes(RemoteSettings.MANAGED_CLASSIFIER_TAG);
                foreach (XmlNode managed_clasiifier_node in managed_classifier_nodes)
                    this.ManagedModels.Add(managed_clasiifier_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNode is_apo_ident_2_1_node = parent_node.SelectNodes(RemoteSettings.IS_APO_IDENT_2_1_TAG)[0];
                this.IsApoIdent_2_1 = Boolean.Parse(is_apo_ident_2_1_node.InnerText);
            }
            catch (Exception) { }

            try
            {
                XmlNode install_date_node = parent_node.SelectNodes(RemoteSettings.INSTALL_DATE_TAG)[0];
                this.InstallDate = DateTime.Parse(install_date_node.InnerText, CultureInfo.InvariantCulture);
            }
            catch (Exception) { }
        }

        public override void WriteToXml(XmlDocument doc, XmlNode parent)
        {
  
            XmlNode url_node = doc.CreateElement(RemoteSettings.URL_TAG);
            url_node.InnerText = this.Url;
            parent.AppendChild(url_node);

            XmlNode port_node = doc.CreateElement(RemoteSettings.TCP_PORT_TAG);
            port_node.InnerText = this.TcpPort.ToString();
            parent.AppendChild(port_node);

            XmlNode locale_node = doc.CreateElement(RemoteSettings.LOCALE_TAG);
            locale_node.InnerText = this.Locale.ToString();
            parent.AppendChild(locale_node);

            XmlNode remember_node = doc.CreateElement(RemoteSettings.REMEMBER_UPDATE_INFO_TAG);
            remember_node.InnerText = this.ReleaseExpirationTime.ToString(CultureInfo.InvariantCulture);
            parent.AppendChild(remember_node);

            XmlNode validation_docu_node = doc.CreateElement(RemoteSettings.UPDATE_VALIDATION_DOCU_TAG);
            validation_docu_node.InnerText = this.UpdateValidationPdfs.ToString();
            parent.AppendChild(validation_docu_node);

            XmlNode other_pdfs_node = doc.CreateElement(RemoteSettings.UPDATE_OTHER_PDFS_TAG);
            other_pdfs_node.InnerText = this.UpdateSubstancePdfs.ToString();
            parent.AppendChild(other_pdfs_node);

            XmlNode update_certificate_node = doc.CreateElement(RemoteSettings.UPDATE_CERTIFICATE_TAG);
            update_certificate_node.InnerText = this.UpdateUpdateCertificate.ToString();
            parent.AppendChild(update_certificate_node);

            XmlNode update_im_license_node = doc.CreateElement(RemoteSettings.UPDATE_IM_LICENSE_TAG);
            update_im_license_node.InnerText = this.UpdateLicenceText.ToString();
            parent.AppendChild(update_im_license_node);

            XmlNode update_additional_tests_node = doc.CreateElement(RemoteSettings.UPDATE_ADDITIONAL_TESTS_PDFS_TAG);
            update_additional_tests_node.InnerText = this.UpdateAdditionalTestsPdfs.ToString();
            parent.AppendChild(update_additional_tests_node);

            foreach (string validated_classifier in this.ValidatedModels)
            {
                XmlNode validated_classifier_node = doc.CreateElement(RemoteSettings.VALIDATED_CLASSIFIER_TAG);
                validated_classifier_node.InnerText = validated_classifier;
                parent.AppendChild(validated_classifier_node);
            }

            foreach (string additional_classifier in this.AdditionalTestedModels)
            {
                XmlNode additional_classifier_node = doc.CreateElement(RemoteSettings.ADDITIONAL_TESTED_CLASSIFIER_TAG);
                additional_classifier_node.InnerText = additional_classifier;
                parent.AppendChild(additional_classifier_node);
            }

            if (this.TestVersion != null)
            {
                XmlNode test_version_node = doc.CreateElement(RemoteSettings.TEST_VERSION_TAG);
                test_version_node.InnerText = this.TestVersion.ToString();
                parent.AppendChild(test_version_node);
            }

            foreach (string managed_classifier in this.ManagedModels)
            {
                XmlNode managed_classifier_node = doc.CreateElement(RemoteSettings.MANAGED_CLASSIFIER_TAG);
                managed_classifier_node.InnerText = managed_classifier;
                parent.AppendChild(managed_classifier_node);
            }

            XmlNode is_apo_ident_2_1_node = doc.CreateElement(RemoteSettings.IS_APO_IDENT_2_1_TAG);
            is_apo_ident_2_1_node.InnerText = this.IsApoIdent_2_1.ToString();
            parent.AppendChild(is_apo_ident_2_1_node);

            XmlNode install_date_node = doc.CreateElement(RemoteSettings.INSTALL_DATE_TAG);
            install_date_node.InnerText = this.InstallDate.ToString(CultureInfo.InvariantCulture);
            parent.AppendChild(install_date_node);
        }

        public override RemoteSettings Clone()
        {
            RemoteSettings tmp = this.GetInstance();
            tmp.ModuleLocation = this.ModuleLocation;
            tmp.Url = this.Url;
            tmp.TcpPort = this.TcpPort;

            tmp.ModuleVersion = this.ModuleVersion;
            tmp.ServerSuffix = this.ServerSuffix;
            tmp.Locale = this.Locale;

            tmp.ReleaseExpirationTime = this.ReleaseExpirationTime;
            tmp.UpdateValidationPdfs = this.UpdateValidationPdfs;
            tmp.UpdateSubstancePdfs = this.UpdateSubstancePdfs;
            this.UpdateLicenceText = this.UpdateLicenceText;
            tmp.UpdateUpdateCertificate = this.UpdateUpdateCertificate;
            tmp.UpdateAdditionalTestsPdfs = this.UpdateAdditionalTestsPdfs;

            tmp.ValidatedModels = new List<string>(this.ValidatedModels);
            tmp.AdditionalTestedModels = new List<string>(this.AdditionalTestedModels);
            tmp.ManagedModels = new List<string>(this.ManagedModels);

            tmp.IsApoIdent_2_1 = this.IsApoIdent_2_1;

            return tmp;
        }

        protected override bool SettingsChanged()
        {
            if (this.Stashed == null)
                return false;

            if (this.Stashed.ModuleLocation != this.ModuleLocation)
                return true;

            if (this.ModuleLocation == RemoteModuleLocationTypes.Custom)
            {
                return this.Stashed.Url != this.Url ||
                       this.Stashed.TcpPort != this.TcpPort;
            }

            return false;
        }

        public string RemoteAddress
        {
            get
            {
                string current_server_address = String.Empty;
                switch (this.ModuleLocation)
                {
                    case RemoteModuleLocationTypes.Local:
                        current_server_address = "localhost";
                        break;

                    case RemoteModuleLocationTypes.Custom:
                        current_server_address = this.Url;
                        break;

                    default:
                        break;
                }
                return current_server_address;
            }
        }

        protected abstract RemoteSettings GetInstance();
        public abstract int RemotePort { get; }

        public RemoteModuleLocationTypes ModuleLocation { get; set; }
        public string Url { get; set; }
        public int TcpPort { get; set; }
        public string ModuleVersion { get; set; }
        public DateTime ReleaseExpirationTime { get; set; }
        public LocaleType Locale { get; set; }
        public string ServerSuffix { get; set; }
        public bool UpdateValidationPdfs { get; set; }
        public bool UpdateSubstancePdfs { get; set; }
        public bool UpdateUpdateCertificate { get; set; }
        public bool UpdateAdditionalTestsPdfs { get; set; }
        public bool UpdateLicenceText { get; set; }
        public List<string> ValidatedModels { get; set; }
        public List<string> AdditionalTestedModels { get; set; }
        public bool? TestVersion { get; set; }
        public List<string> ManagedModels { get; set; }
        public bool IsApoIdent_2_1 { get; set; }
        public DateTime InstallDate { get; set; }
    }
}
