// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2017 Thomas Klose & Torsten Schache, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.


using System;
using System.Xml;

using Hiperscan.Common.I18n;
using Hiperscan.Extensions.ApoIdentCommon;
using Hiperscan.Unix;


namespace Hiperscan.Extensions.ApoIdent
{
    public partial class Configurations
    {
        public enum FilenameStartTypes
        {
            SubstanceName,
            LatinName,
        }

        public enum ReportCountryType
        {
            Germany,
            Austria,
            GreatBritain,
            Switzerland
        }

        public class ProfilePreferences : Preferences<ProfilePreferences>
        {
            public const string PROFILE_TAG = "Profile";
            private const string COMPANY_TAG = "Company";
            private const string STREET_TAG = "Street";
            private const string TOWN_TAG = "Town";
            private const string FILE_NAMES_TAG = "FileNameStartsWith";
            private const string ARCHIVE_TAG = "Archive";
            private const string COUNTRY_TAG = "Country";
            private const string BAK_MARKING_ACTIVATED_TAG = "BAKMarkingActivated";
            private const string DIFFERENCE_TAG = "Difference";
            private const string BASE64_ADDRESS_DATA_TAG = "Base64AddressData";
            private const string MERGED_ADDITIONAL_DATA_TAG = "MergedAdditionalData";
            private const string ARCHIVE_CREATED_TAG = "ArchiveCreated";
            private const string DONT_SHOW_NOT_MEASURABLE_DIALOG_TAG = "DontShowNotMeasurableDialog";
            private const string MANDATORY_FOR_ADD_TEST_TAG = "MandatoryForAddTest";
            private const string PRINT_VALIDATION_WITHIN_PROTOCOL = "PrintValidationWithinProtocol";


            private const string NAME_ATTRIBUTE = "Name";

            public static readonly string DEFAULT_CUSTOMER_NUMBER = "00000";
            public static readonly string DEFAULT_NAME = Catalog.GetString("Demo profile");
            public static readonly string DEFAULT_COMPANY = Catalog.GetString("Unknown organisation");
            public static readonly string DEFAULT_STREET = Catalog.GetString("Unknown street");
            public static readonly string DEFAULT_TOWN = Catalog.GetString("Unknown town");

            public static bool AutoConvertToBase64 = false;

            public ProfilePreferences() : base()
            {

            }

            public ProfilePreferences(XmlNode profile_node) : base(profile_node)
            {

            }

            protected override void Init(XmlNode parent_node = null)
            {
                this.Name = String.Empty;
                this.CustomerNumber = String.Empty;
                this.Company = String.Empty;
                this.Street = String.Empty;
                this.Town = String.Empty;
                this.Archive = String.Empty;

                this.FileNameStart = FilenameStartTypes.SubstanceName;
                this.ExchangeData = new DataExchangeApoIdent();

                switch (Locale.Language)
                {
                    case "de":
                        switch (Locale.Country)
                        {

                            case "at":
                                this.ReportCountry = ReportCountryType.Austria;
                                break;

                            case "ch":
                                this.ReportCountry = ReportCountryType.Switzerland;
                                break;

                            default:
                                this.ReportCountry = ReportCountryType.Germany;
                                break;

                        }
                        break;

                    default:
                        this.ReportCountry = ReportCountryType.GreatBritain;
                        break;
                }

                this.BAKMarkingActivated = false;
                this.ShowDifference = false;
                this.IgnoreMissingArchive = false;

                base.Init(parent_node);
            }

            protected override void Read(XmlNode parent_node)
            {
                this.MergedAdditionalData = false;

                try
                {
                    this.Name = parent_node.Attributes[ProfilePreferences.NAME_ATTRIBUTE].Value;
                }
                catch (Exception) { return; }

                string[] decoded_address_data = null;
                try
                {
                    XmlNode base64_address_node = parent_node.SelectNodes(ProfilePreferences.BASE64_ADDRESS_DATA_TAG)[0];
                    if (base64_address_node != null)
                    {
                        decoded_address_data = Base64AddressData.Decode(base64_address_node.InnerText);
                        if (decoded_address_data.Length < 6)
                            throw new Exception(Catalog.GetString("Invalid number of entries in decoded address data."));
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine("Using default address data.");
                    decoded_address_data = new string[6];
                    decoded_address_data[0] = ProfilePreferences.DEFAULT_CUSTOMER_NUMBER;
                    decoded_address_data[1] = ProfilePreferences.DEFAULT_COMPANY;
                    decoded_address_data[2] = ProfilePreferences.DEFAULT_STREET;
                    decoded_address_data[3] = ProfilePreferences.DEFAULT_TOWN;
                    decoded_address_data[4] = Plugin.name + " " + Plugin.version;
                    decoded_address_data[5] = DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture);
                }

                if (decoded_address_data != null)
                {
                    try
                    {
                        this.CustomerNumber = decoded_address_data[0];
                        this.Company = decoded_address_data[1];
                        this.Street = decoded_address_data[2];
                        this.Town = decoded_address_data[3];
                        this.Base64ConversionCreator = decoded_address_data[4];
                        this.Base64ConversionTimestamp = DateTime.Parse(decoded_address_data[5], System.Globalization.CultureInfo.InvariantCulture);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Cannot decode address data: " + ex.Message);
                    }
                }
                else
                {
                    if (ProfilePreferences.AutoConvertToBase64 == false)
                        return;

                    this.CustomerNumber = ProfilePreferences.DEFAULT_CUSTOMER_NUMBER;

                    try
                    {
                        XmlNode company_node = parent_node.SelectNodes(ProfilePreferences.COMPANY_TAG)[0];
                        this.Company = company_node.InnerText;
                    }
                    catch (Exception) { }

                    try
                    {
                        XmlNode street_node = parent_node.SelectNodes(ProfilePreferences.STREET_TAG)[0];
                        this.Street = street_node.InnerText;
                    }
                    catch (Exception) { }

                    try
                    {
                        XmlNode town_node = parent_node.SelectNodes(ProfilePreferences.TOWN_TAG)[0];
                        this.Town = town_node.InnerText;
                    }
                    catch (Exception) { }
                }

                try
                {
                    XmlNode archive_node = parent_node.SelectNodes(ProfilePreferences.ARCHIVE_TAG)[0];
                    this.Archive = archive_node.InnerText;
                }
                catch (Exception) { }

                try
                {
                    XmlNode country_node = parent_node.SelectNodes(ProfilePreferences.COUNTRY_TAG)[0];
                    this.ReportCountry = (ReportCountryType)Enum.Parse(typeof(ReportCountryType), country_node.InnerText, true);
                }
                catch (Exception) { }

                try
                {
                    XmlNode bak_node = parent_node.SelectNodes(ProfilePreferences.BAK_MARKING_ACTIVATED_TAG)[0];
                    this.BAKMarkingActivated = Boolean.Parse(bak_node.InnerText);
                }
                catch (Exception) { }

                try
                {
                    XmlNode difference_node = parent_node.SelectNodes(ProfilePreferences.DIFFERENCE_TAG)[0];
                    this.ShowDifference = Boolean.Parse(difference_node.InnerText);
                }
                catch (Exception) { }

                try
                {
                    XmlNode management_node = parent_node.SelectNodes(DataExchange.MANAGEMENT_TAG)[0];
                    this.ExchangeData = DataExchange.ReadFromConfig(management_node);
                }
                catch (Exception) { }

                try
                {
                    XmlNode file_name_node = parent_node.SelectNodes(ProfilePreferences.FILE_NAMES_TAG)[0];
                    this.FileNameStart = (FilenameStartTypes)Enum.Parse(typeof(FilenameStartTypes), file_name_node.InnerText, true);
                }
                catch (Exception) { }

                try
                {
                    XmlNode merged_additional_data_node = parent_node.SelectNodes(ProfilePreferences.MERGED_ADDITIONAL_DATA_TAG)[0];
                    this.MergedAdditionalData = Boolean.Parse(merged_additional_data_node.InnerText);
                }
                catch (Exception) { }

                try
                {
                    XmlNode dont_show_not_measurable_node = parent_node.SelectNodes(ProfilePreferences.DONT_SHOW_NOT_MEASURABLE_DIALOG_TAG)[0];
                    this.DontShowNotMeasurableDialogAgain = Boolean.Parse(dont_show_not_measurable_node.InnerText);
                }
                catch (Exception) { }

                try
                {
                    XmlNode deactivate_add_tests_node = parent_node.SelectNodes(ProfilePreferences.MANDATORY_FOR_ADD_TEST_TAG)[0];
                    this.MandatoryForComplementaryTest = Boolean.Parse(deactivate_add_tests_node.InnerText);
                }
                catch (Exception) { }

                try
                {
                    XmlNode print_validation_node = parent_node.SelectNodes(ProfilePreferences.PRINT_VALIDATION_WITHIN_PROTOCOL)[0];
                    this.PrintValidationWhitinProtocol = Boolean.Parse(print_validation_node.InnerText);
                }
                catch (Exception) { }
            }

            public override void WriteToXml(XmlDocument doc, XmlNode parent)
            {
                XmlNode profile_node = doc.CreateElement(ProfilePreferences.PROFILE_TAG);
                parent.AppendChild(profile_node);

                XmlAttribute name_attribute = doc.CreateAttribute(ProfilePreferences.NAME_ATTRIBUTE);
                name_attribute.Value = this.Name;
                profile_node.Attributes.Append(name_attribute);

                XmlNode company_node = doc.CreateElement(ProfilePreferences.COMPANY_TAG);
                company_node.InnerText = this.Company;
                profile_node.AppendChild(company_node);

                XmlNode street_node = doc.CreateElement(ProfilePreferences.STREET_TAG);
                street_node.InnerText = this.Street;
                profile_node.AppendChild(street_node);

                XmlNode town_node = doc.CreateElement(ProfilePreferences.TOWN_TAG);
                town_node.InnerText = this.Town;
                profile_node.AppendChild(town_node);

                string[] entries = new string[6];
                entries[0] = this.CustomerNumber;
                entries[1] = this.Company;
                entries[2] = this.Street;
                entries[3] = this.Town;
                entries[4] = this.Base64ConversionCreator ?? Plugin.name + " " + Plugin.version;
                entries[5] = this.Base64ConversionTimestamp?.ToString(System.Globalization.CultureInfo.InvariantCulture) ?? DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture);
                XmlNode base64_address_node = doc.CreateElement(ProfilePreferences.BASE64_ADDRESS_DATA_TAG);
                base64_address_node.InnerText = Base64AddressData.Encode(entries);
                profile_node.AppendChild(base64_address_node);

                XmlNode archive_node = doc.CreateElement(ProfilePreferences.ARCHIVE_TAG);
                archive_node.InnerText = this.Archive;
                profile_node.AppendChild(archive_node);

                this.ExchangeData.WriteToXml(doc, profile_node);

                XmlNode country_node = doc.CreateElement(ProfilePreferences.COUNTRY_TAG);
                country_node.InnerText = this.ReportCountry.ToString();
                profile_node.AppendChild(country_node);

                XmlNode bak_node = doc.CreateElement(ProfilePreferences.BAK_MARKING_ACTIVATED_TAG);
                bak_node.InnerText = this.BAKMarkingActivated.ToString();
                profile_node.AppendChild(bak_node);

                XmlNode difference_node = doc.CreateElement(ProfilePreferences.DIFFERENCE_TAG);
                difference_node.InnerText = this.ShowDifference.ToString();
                profile_node.AppendChild(difference_node);

                XmlNode file_name_node = doc.CreateElement(ProfilePreferences.FILE_NAMES_TAG);
                file_name_node.InnerText = this.FileNameStart.ToString();
                profile_node.AppendChild(file_name_node);

                XmlNode merged_additional_date_node = doc.CreateElement(ProfilePreferences.MERGED_ADDITIONAL_DATA_TAG);
                merged_additional_date_node.InnerText = this.MergedAdditionalData.ToString();
                profile_node.AppendChild(merged_additional_date_node);

                XmlNode dont_show_not_meaurable_node = doc.CreateElement(ProfilePreferences.DONT_SHOW_NOT_MEASURABLE_DIALOG_TAG);
                dont_show_not_meaurable_node.InnerText = this.DontShowNotMeasurableDialogAgain.ToString();
                profile_node.AppendChild(dont_show_not_meaurable_node);

                XmlNode deactivate_add_tests_node = doc.CreateElement(ProfilePreferences.MANDATORY_FOR_ADD_TEST_TAG);
                deactivate_add_tests_node.InnerText = this.MandatoryForComplementaryTest.ToString();
                profile_node.AppendChild(deactivate_add_tests_node);

                XmlNode print_validation_node = doc.CreateElement(ProfilePreferences.PRINT_VALIDATION_WITHIN_PROTOCOL);
                print_validation_node.InnerText = this.PrintValidationWhitinProtocol.ToString();
                profile_node.AppendChild(print_validation_node);
            }

            public void ReadAddtionalInfos()
            {
                this.AdditionalCompletionEntries = AdditionalTestEntries.Read();
                if (this.MergedAdditionalData == false)
                {
                    AdditionalTestEntries.Merge(this.AdditionalCompletionEntries);
                    this.MergedAdditionalData = true;
                }
            }

            public void ReadNotMeasurableSubstances(IdentServerClient client)
            {
                this.SubstanceExtension = new SubstanceExtension(client);
            }

            public override ProfilePreferences Clone()
            {
                ProfilePreferences tmp = new ProfilePreferences();
                tmp.Name = this.Name;
                tmp.CustomerNumber = this.CustomerNumber;
                tmp.Company = this.Company;
                tmp.Street = this.Street;
                tmp.Town = this.Town;
                tmp.Base64ConversionCreator = this.Base64ConversionCreator;
                tmp.Base64ConversionTimestamp = this.Base64ConversionTimestamp;
                tmp.FileNameStart = this.FileNameStart;
                tmp.Archive = this.Archive;
                tmp.ExchangeData = this.ExchangeData.Clone(this.ExchangeData.ProtocolType);
                tmp.ReportCountry = this.ReportCountry;
                tmp.BAKMarkingActivated = this.BAKMarkingActivated;
                tmp.ShowDifference = this.ShowDifference;
                tmp.IgnoreMissingArchive = this.IgnoreMissingArchive;
                tmp.AdditionalCompletionEntries = this.AdditionalCompletionEntries;
                tmp.SubstanceExtension = this.SubstanceExtension;
                tmp.MergedAdditionalData = this.MergedAdditionalData;
                tmp.MandatoryForComplementaryTest = this.MandatoryForComplementaryTest;
                tmp.DontShowNotMeasurableDialogAgain = this.DontShowNotMeasurableDialogAgain;
                tmp.PrintValidationWhitinProtocol = this.PrintValidationWhitinProtocol;
                tmp.ArchiveMissing = this.ArchiveMissing;
                return tmp;
            }

            protected override bool SettingsChanged()
            {
                this.ArchiveChanged = false;

                if (this.Stashed == null)
                {
                    this.ArchiveChanged = true;
                    return true;
                }

                if (this.Stashed.Archive != this.Archive)
                {
                    this.ArchiveChanged = true;
                    return true;
                }

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

                if (this.Stashed.ExchangeData.ProtocolType != this.ExchangeData.ProtocolType)
                    return true;
 
                if (this.Stashed.ExchangeData.IsActivated != this.ExchangeData.IsActivated)
                    return true;

                if (this.Stashed.ExchangeData.WorkingDir != this.ExchangeData.WorkingDir)
                    return true;

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

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

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

                return false;
            }

            public string Name { get; set; }
            public string CustomerNumber { get; set; }
            public string Company { get; set; }
            public string Street { get; set; }
            public string Town { get; set; }
            public string Base64ConversionCreator { get; set; }
            public DateTime? Base64ConversionTimestamp { get; set; }
            public FilenameStartTypes FileNameStart { get; set; }
            public string Archive { get; set; }
            public DataExchange ExchangeData { get; set; }
            public ReportCountryType ReportCountry { get; set; }
            public bool BAKMarkingActivated { get; set; }
            public bool ShowDifference { get; set; }
            public bool IgnoreMissingArchive { get; set; }
            public AdditionalTestEntries AdditionalCompletionEntries { get; set; }
            public SubstanceExtension SubstanceExtension { get; set; } = null;
            public bool MergedAdditionalData { get; set; } = true;
            public bool DontShowNotMeasurableDialogAgain { get; set; } = false;
            public bool MandatoryForComplementaryTest { get; set; } = true;
            public bool PrintValidationWhitinProtocol { get; set; } = true;
            public bool ArchiveMissing { get; set; } = true;
            public bool ArchiveChanged { get; set; } = false;
           
        }
    }
}

