// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2018 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.Collections.Generic;
using System.Xml;
using Hiperscan.Common;
using Hiperscan.Unix;

namespace Hiperscan.ApoIdentCommon.ApoConfig.ThirdPartyDataExchange
{
    public enum ProtocolType
    {
        [StringValue("Apo-Ident")]                  ApoIdent,
        [StringValue("Dr. Lennartz Laborprogramm")] Lennartz,
    }

    public abstract class DataExchange : Dictionary<string, ExchangeDataSet>
    {
        public const string MANAGEMENT_TAG      = "ReportManagement";
        private const string TYPE_ATTRINUTE     = "ManagementBy";
        private const string WORKING_DIR_TAG    = "WorkingDirectory";
        private const string AUTO_CONFIG_TAG    = "AutoConfig";

        protected DataExchange()
        {
            this.WorkingDir     = this.DefaultWorkingDir;
            this.IsActivated    = true;
        }

        public void WriteToXml(XmlDocument doc, XmlNode parent)
        {
            XmlNode management_node = doc.CreateElement(DataExchange.MANAGEMENT_TAG);
            parent.AppendChild(management_node);

            XmlAttribute type_attribute = doc.CreateAttribute(DataExchange.TYPE_ATTRINUTE);
            type_attribute.Value = this.ProtocolType.ToString();
            management_node.Attributes.Append(type_attribute);

            XmlNode directory_node = doc.CreateElement(DataExchange.WORKING_DIR_TAG);
            directory_node.InnerText = this.WorkingDir;
            management_node.AppendChild(directory_node);
        }


        protected abstract DateTime? ConvertToExpiryDate(string date);
        public abstract void ImportFiles();
        public abstract void ExportFile(string protocol_pdf_file);
        protected abstract void DeleteImportFile();
        public abstract string GetReadingErrorMessage(Exception ex);


        public DataExchange Clone(ProtocolType type)
        {
            DataExchange clone = null;
            switch(type)
            {
                case ProtocolType.ApoIdent:
                    clone =new DataExchangeApoIdent();
                    break;

                case ProtocolType.Lennartz:
                    clone =new DataExchangeLennartz();
                    break;

                default:
                    break;
            }

            clone.WorkingDir        = this.WorkingDir;
            clone.CurrentDataSetKey = this.CurrentDataSetKey;
            clone.IsActivated       = this.IsActivated;

            foreach (string key in this.Keys)
                clone.Add(key, this[key].Clone());
            
            return clone;
        }

        public static DataExchange Create(ProtocolType type)
        {
            DataExchange instance = null;
            switch (type)
            {
                case ProtocolType.ApoIdent:
                    instance = new DataExchangeApoIdent();
                    break;

                case ProtocolType.Lennartz:
                    instance = new DataExchangeLennartz();
                    break;

                default:
                    break;
            }

            return instance;
        }

        public static DataExchange ReadFromConfig(XmlNode management_node)
        {
            DataExchange exchange = null;
            bool success = true;
            try
            {
                ProtocolType type = (ProtocolType)Enum.Parse(typeof(ProtocolType),
                                                              management_node.Attributes[DataExchange.TYPE_ATTRINUTE].Value);
                switch (type)
                {
                    case ProtocolType.ApoIdent:
                        exchange = new DataExchangeApoIdent();
                        break;

                    case ProtocolType.Lennartz:
                        exchange = new DataExchangeLennartz();
                        break;

                    default:
                        break;
                }
            }

            catch (Exception)
            {
                exchange = new DataExchangeApoIdent();
                success = false;
            }

            if (success == true)
            {
                try
                {
                    exchange.WorkingDir = management_node.SelectNodes(DataExchange.WORKING_DIR_TAG)[0].InnerText.Trim();
                    if (String.IsNullOrEmpty(exchange.WorkingDir) == true)
                        exchange.WorkingDir = exchange.DefaultWorkingDir;
                }
                catch (Exception) { }

                try
                {
                    exchange.WorkingDir = management_node.SelectNodes(DataExchange.WORKING_DIR_TAG)[0].InnerText.Trim();
                    if (String.IsNullOrEmpty(exchange.WorkingDir) == true)
                        exchange.WorkingDir = exchange.DefaultWorkingDir;
                }
                catch (Exception) { }
            }

            return exchange;
        }

        public abstract string DefaultWorkingDir            {get;}
        public abstract string DefaultImportFileExtension   {get;}
        public abstract string DefaultExportFileExtension   {get;}
        public abstract ProtocolType ProtocolType           {get;}
        public abstract string ApplicationName              {get;}

        public string WorkingDir            {get; set;} = String.Empty;
        public string CurrentDataSetKey     {get; set;} = String.Empty;
        public bool IsActivated             {get; set;} = false;
    }
}
