// 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 System.Globalization;

using Hiperscan.I18n;
using System.Collections.Generic;

namespace Hiperscan.Extensions.ApoIdent
{
	public enum IdentificationMode
	{
		Local,
		Custom
	}

	public class AcquisitionSettings
	{
		public event EventHandler AcquisitionSettingsChanged = null;

		public const string ACQUISITION_SETTINGS_TAG 	= "AcquisitionSettings";
		private const string IDENTIFICATION_MODE_TAG	= "IdentificationMode";
		private const string URL_TAG 					= "Url";
		private const string TCP_PORT_TAG 				= "Tcp";

		private const string IDENT_SERVER_VERSION_TAG	= "IdentServerVersion";
		private const string IDENT_SERVER_SUFFIX_TAG	= "IdentServerSuffix";
		private const string ARCHIVE_DOKU_TAG			= "ArchiveDocu";
		private const string REMEMBER_UPDATE_INFO_TAG	= "RememberUpdateInfo";
		private const string LOCALE_TAG				    = "Location";
        private const string TEST_VERSION_TAG           = "TestVersion";
		private const string UPDATE_VALIDATION_DOCU_TAG	= "UpdateValidationDocu";
		private const string UPDATE_OTHER_PDFS_TAG		= "UpdateSubstancePdfs";
		private const string UPDATE_CERTIFICATE_TAG		= "UpdateCertificate";
        private const string UPDATE_ADDITIONAL_TESTS_PDFS_TAG = "UpdateAdditionalTestsPdfs";
        private const string VALIDATED_CLASSIFIER_TAG   = "ValidatedClassifier";

		public AcquisitionSettings()
		{
			this.IdentificationMode			= IdentificationMode.Local;
			this.Url 						= String.Empty;
			this.TcpPort					= -1;
			this.IdentServerVersion			= String.Empty;
			this.IdentServerSuffix			= String.Empty;
            this.Locale					    = Hiperscan.I18n.Locale.LocaleType.Unknown;
			this.ReleaseExpirationTime		= DateTime.MaxValue;
			this.UpdateValidationDocu		= false;
			this.UpdateSubstancePdfs		= false;
			this.UpdateUpdateCertificate	= false;
            this.UpdateAdditionalTestsPdfs  = false;
            this.ValidatedClassifiers       = new List<string>();
            this.TestVersion                = null;
		}

		public AcquisitionSettings(XmlNode acquisition_settings_node) : this()
		{
			try
			{
				XmlNode identification_mode_node = acquisition_settings_node.SelectNodes(AcquisitionSettings.IDENTIFICATION_MODE_TAG)[0];
				this.IdentificationMode = (IdentificationMode) Enum.Parse(typeof(IdentificationMode), identification_mode_node.InnerText, true);
			}
			catch (Exception){}

			try
			{
				XmlNode url_node = acquisition_settings_node.SelectNodes(AcquisitionSettings.URL_TAG)[0];
				this.Url = url_node.InnerText;
			}
			catch (Exception){}

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

			try
			{
				XmlNode server_node = acquisition_settings_node.SelectNodes(AcquisitionSettings.IDENT_SERVER_VERSION_TAG)[0];
				this.IdentServerVersion = server_node.InnerText;
			}
			catch (Exception){}

			try
			{
				XmlNode suffix_node = acquisition_settings_node.SelectNodes(AcquisitionSettings.IDENT_SERVER_SUFFIX_TAG)[0];
				this.IdentServerSuffix = suffix_node.InnerText;
			}
			catch (Exception){}

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

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

			try
			{
				XmlNode update_validation_node = acquisition_settings_node.SelectNodes(AcquisitionSettings.UPDATE_VALIDATION_DOCU_TAG)[0];
				this.UpdateValidationDocu = Boolean.Parse(update_validation_node.InnerText);
			}
			catch (Exception){}

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

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

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

            try
            {
                XmlNodeList validated_classifier_nodes =  acquisition_settings_node.SelectNodes(AcquisitionSettings.VALIDATED_CLASSIFIER_TAG);
                foreach (XmlNode validated_clasiifier_node in validated_classifier_nodes)
                    this.ValidatedClassifiers.Add(validated_clasiifier_node.InnerText);
            }
            catch(Exception){}

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

		public void WriteToXml(XmlDocument doc, XmlNode parent)
		{
			XmlNode acquisition_settings_node_node = doc.CreateElement(AcquisitionSettings.ACQUISITION_SETTINGS_TAG);
			parent.AppendChild(acquisition_settings_node_node);

			XmlNode identification_mode_node = doc.CreateElement(AcquisitionSettings.IDENTIFICATION_MODE_TAG);
			identification_mode_node.InnerText = this.IdentificationMode.ToString();
			acquisition_settings_node_node.AppendChild(identification_mode_node);

			XmlNode url_node = doc.CreateElement(AcquisitionSettings.URL_TAG);
			url_node.InnerText = this.Url;
			acquisition_settings_node_node.AppendChild(url_node);

			XmlNode port_node = doc.CreateElement(AcquisitionSettings.TCP_PORT_TAG);
			port_node.InnerText = this.TcpPort.ToString();
			acquisition_settings_node_node.AppendChild(port_node);

			XmlNode server_node = doc.CreateElement(AcquisitionSettings.IDENT_SERVER_VERSION_TAG);
			server_node.InnerText = this.IdentServerVersion;
			acquisition_settings_node_node.AppendChild(server_node);

			XmlNode suffix_node = doc.CreateElement(AcquisitionSettings.IDENT_SERVER_SUFFIX_TAG);
			suffix_node.InnerText = this.IdentServerSuffix;
			acquisition_settings_node_node.AppendChild(suffix_node);

            XmlNode locale_node = doc.CreateElement(AcquisitionSettings.LOCALE_TAG);
            locale_node.InnerText = this.Locale.ToString();
			acquisition_settings_node_node.AppendChild(locale_node);

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

			XmlNode validation_docu_node = doc.CreateElement(AcquisitionSettings.UPDATE_VALIDATION_DOCU_TAG);
			validation_docu_node.InnerText = this.UpdateValidationDocu.ToString();
			acquisition_settings_node_node.AppendChild(validation_docu_node);

			XmlNode other_pdfs_node = doc.CreateElement(AcquisitionSettings.UPDATE_OTHER_PDFS_TAG);
			other_pdfs_node.InnerText = this.UpdateSubstancePdfs.ToString();
			acquisition_settings_node_node.AppendChild(other_pdfs_node);

			XmlNode update_certificate_node = doc.CreateElement(AcquisitionSettings.UPDATE_CERTIFICATE_TAG);
			update_certificate_node.InnerText = this.UpdateUpdateCertificate.ToString();
			acquisition_settings_node_node.AppendChild(update_certificate_node);

            XmlNode update_additional_tests_node = doc.CreateElement(AcquisitionSettings.UPDATE_ADDITIONAL_TESTS_PDFS_TAG);
            update_additional_tests_node.InnerText = this.UpdateAdditionalTestsPdfs.ToString();
            acquisition_settings_node_node.AppendChild(update_additional_tests_node);

            foreach (string validated_classifier in this.ValidatedClassifiers)
            {
                XmlNode validated_classifier_node = doc.CreateElement(AcquisitionSettings.VALIDATED_CLASSIFIER_TAG);
                validated_classifier_node.InnerText = validated_classifier;
                acquisition_settings_node_node.AppendChild(validated_classifier_node);
            }

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

		public AcquisitionSettings Clone()
		{
			AcquisitionSettings tmp 	= new AcquisitionSettings();
			tmp.IdentificationMode		= this.IdentificationMode;
			tmp.Url						= this.Url;
			tmp.TcpPort					= this.TcpPort;

			tmp.IdentServerVersion		= this.IdentServerVersion;
			tmp.IdentServerSuffix		= this.IdentServerSuffix;
			tmp.Locale			        = this.Locale;

			tmp.ReleaseExpirationTime	    = this.ReleaseExpirationTime;
			tmp.UpdateValidationDocu 	    = this.UpdateValidationDocu;
			tmp.UpdateSubstancePdfs		    = this.UpdateSubstancePdfs;
			tmp.UpdateUpdateCertificate	    = this.UpdateUpdateCertificate;
            tmp.UpdateAdditionalTestsPdfs   = this.UpdateAdditionalTestsPdfs;

            tmp.ValidatedClassifiers   = new List<string>(this.ValidatedClassifiers);

			return tmp;			
		}

		public bool IdentServerSettingsCanged
        {
            get
            {
                if (this.Stashed == null)
                    return false;
                
				return this.Stashed.IdentificationMode != this.IdentificationMode ||
						   this.Stashed.Url != this.Url ||
						   this.Stashed.TcpPort != this.TcpPort;
            }
        }
      
		public void Stash()
		{
			this.Stashed = this.Clone();
		}

		public void Unstash()
		{
			if (this.AcquisitionSettingsChanged != null)
				this.AcquisitionSettingsChanged(this, EventArgs.Empty);

			this.Stashed = null;
		}
			
		private AcquisitionSettings Stashed			    {get; set;}
		public IdentificationMode IdentificationMode	{get; set;}
		public string Url								{get; set;}
		public int TcpPort								{get; set;}
		public string IdentServerVersion				{get; set;}
		public DateTime ReleaseExpirationTime			{get; set;}
        public Locale.LocaleType Locale 			    {get; set;}
		public string IdentServerSuffix					{get; set;}
		public bool UpdateValidationDocu				{get; set;}
		public bool UpdateSubstancePdfs					{get; set;}
		public bool UpdateUpdateCertificate				{get; set;}
        public bool UpdateAdditionalTestsPdfs           {get; set;}
        public List<string> ValidatedClassifiers        {get; set;}
        public bool? TestVersion                        {get; set;}
	}
}

