using System;
using System.Collections.Generic;
using Hiperscan.AnalysisModule;
using Hiperscan.AnalysisModule.Authentification;
using Hiperscan.AnalysisModule.Identification;
using Hiperscan.AnalysisModule.Identification.Result;
using Hiperscan.AnalysisModule.Quantification;
using Hiperscan.AnalysisModule.Remoting;
using Hiperscan.ApoIdentCommon.ApoConfig;
using Hiperscan.ApoIdentCommon.ApoConfig.IO;
using Hiperscan.SGS;
using Hiperscan.Spectroscopy;

namespace Hiperscan.ApoIdentCore.Remoting
{
    public partial class RemoteManager
    {
        public event EventHandler StateChanged = null;
        public event EventHandler LoadingStarted = null;
        public event EventHandler LoadingProgressed = null;
        public event EventHandler LoadingFinished = null;

        public RemoteManager(IdentModuleSettings ident_settings, 
                             QuantifierModuleSettings quantifier_settings,
                             ApoIdentFileSystem file_system)
        {
            this.IdentSettings = ident_settings;
            this.QuantifierSettings = quantifier_settings;


            this.IdentConnector = new IdentModuleConnector(file_system.MonoExeFile,
                                                                 ident_settings.RemoteAddress,
                                                                 ident_settings.RemotePort);



            this.QuantifierConnector = new QuantifierModuleConnector(file_system.MonoExeFile,
                                                                     quantifier_settings.RemoteAddress,
                                                                     quantifier_settings.RemotePort);
            this.AddEvents();
        
        }


        private void AddEvents()
        {
            this.IdentConnector.StateChanged += (sender, e) => this.StateChanged?.Invoke(sender ,e);
            this.IdentConnector.LoadingDataStarted += (sender, e) => this.LoadingStarted?.Invoke(sender, e);
            this.IdentConnector.LoadingDataProgressed += (sender, e) => this.LoadingProgressed?.Invoke(sender, e);
            this.IdentConnector.LoadingDataFinished += (sender, e) => this.LoadingFinished?.Invoke(sender, e);

            this.QuantifierConnector.StateChanged += (sender, e) => this.StateChanged?.Invoke(sender, e);
            this.QuantifierConnector.LoadingDataStarted += (sender, e) => this.LoadingStarted?.Invoke(sender, e);
            this.QuantifierConnector.LoadingDataProgressed += (sender, e) => this.LoadingProgressed?.Invoke(sender, e);
            this.QuantifierConnector.LoadingDataFinished += (sender, e) => this.LoadingFinished?.Invoke(sender, e);
        }

       
        public RemoteState StartServer(AnalysisType analysis_type)
        {
            RemoteState state = null;

            if (analysis_type == AnalysisType.Identification)
            {
                this.IdentConnector.Start();
                 state = this.IdentConnector.State;
            }
            else
            {
                this.QuantifierConnector.Start();
                state = this.QuantifierConnector.State;
            }

            return state;
        }

        public RemoteState RegisterDevice(AnalysisType analysis_type, IDevice device)
        {
            RemoteState state = null;

            if (analysis_type == AnalysisType.Identification)
            {
                this.IdentConnector.RegisterDevice(device);
                state = this.IdentConnector.State;
            }
            else
            {
                this.QuantifierConnector.RegisterDevice(device);
                state = this.QuantifierConnector.State;
            }

            return state;
        }

        public RemoteState LoadModelData(AnalysisType analysis_type)
        {
            RemoteState state = null;

            if (analysis_type == AnalysisType.Identification)
            {
                this.IdentConnector.LoadModelClassData();
                state = this.IdentConnector.State;
            }
            else
            {
                this.QuantifierConnector.LoadModelClassData();
                state = this.QuantifierConnector.State;
            }

            return state;
        }

        public AnalysisServerInfo GetServerInfo(AnalysisType analysis_type)
        {
            if (analysis_type == AnalysisType.Identification)
                return this.IdentConnector.Info;
            else
                return this.QuantifierConnector.Info;
        }

        public void StopServer(AnalysisType analysis_type)
        {
            if (analysis_type == AnalysisType.Identification)
                this.IdentConnector.Stop();
            else
                this.QuantifierConnector.Stop();
        }

        public bool ServerIsRunning(AnalysisType analysis_type)
        {
            if (analysis_type == AnalysisType.Identification)
                return this.IdentConnector.IsConnected;
            else
                return this.QuantifierConnector.IsConnected;
        }

        public bool ServerIsInstalled(AnalysisType analysis_type)
        {
            if (analysis_type == AnalysisType.Identification)
                return this.IdentConnector.IsInstalled;
            else
                return this.QuantifierConnector.IsInstalled;
        }

        public byte[] GetValidationDocument(IdentModelClass model_class)
        {
            RemoteConnector current = this.GetRemoteConnector(model_class.DatabaseInfo);
            return current.GetValidationDocument(model_class);
        }

        public byte[] GetIdentUpdateChanges()
        {
            return this.IdentConnector.Client.Service.GetUpdateChangesFile();
        }

        public byte[] GetAdditionalTestDocument(IdentModelClass model_class = null)
        {
            if (model_class == null)
                return this.IdentConnector.Client.Service.GetAdditionalTestPdf();
            else
                return this.QuantifierConnector.GetAdditionalTestPdf(model_class);
        }

        public byte[] GetLicense(AnalysisType analysis_type)
        {
            if (analysis_type == AnalysisType.Identification)
                return this.IdentConnector.Client.Service.GetLicense();
            else
                return this.QuantifierConnector.Client.Service.GetLicense();
        }

        public Dictionary<string, byte[]> GetLogFiles(AnalysisType analysis_type)
        {
            if (analysis_type == AnalysisType.Identification)
                return this.IdentConnector.Client.Service.GetLogfiles();
            else
                return this.QuantifierConnector.Client.Service.GetLogfiles();
        }

        public void UpdateAuthentificationSet(IdentModelClass model_class, string substance_id = AuthentificationSet.NO_SUBSTANCE)
        {
            if (model_class.DatabaseInfo.DatabaseType == AccessDatabaseType.UserDefined)
                return;

            RemoteConnector current = this.GetRemoteConnector(model_class.DatabaseInfo);
            current.UpdateAuthentificationSet(model_class, substance_id);
        }

        public RemoteSettings GetSettings(AnalysisType analysis_type)
        {
            if (analysis_type == AnalysisType.Identification)
                return this.IdentSettings;
            else
                return this.QuantifierSettings;
        }

        public ApoIdentResultSet Classify(Spectrum spectrum)
        {
            this.IdentConnector.Analyse(spectrum);
            return this.IdentConnector.Result;
        }

        public PlsResultSet Quantify(Spectrum spectrum)
        {
            this.QuantifierConnector.Analyse(spectrum);
            return this.QuantifierConnector.Result;
        }

        public void DiscardResults()
        {
            this.IdentConnector.DiscartResult();
            this.QuantifierConnector.DiscartResult();
        }

        private RemoteConnector GetRemoteConnector(AccessDatabaseInfo db_info)
        {
            if (this.IdentConnector.Databases.ContainsKey(db_info))
                return this.IdentConnector;

            if (this.QuantifierConnector.Databases.ContainsKey(db_info))
                return this.QuantifierConnector;

            return null;
        }

        private IdentModuleSettings IdentSettings { get; set; }
        private QuantifierModuleSettings QuantifierSettings { get; set; }

        private IdentModuleConnector IdentConnector { get; set; }
        public QuantifierModuleConnector QuantifierConnector { get; set; }
    }
}
