using System;
using System.Collections.Generic;
using System.Linq;
using Toolbox.Docking.Api.Chemical;
using Toolbox.Docking.Api.Control;
using Toolbox.Docking.Api.Data;
using Toolbox.Docking.Api.Objects;
using Toolbox.Docking.Api.Objects.Qsar;
using Toolbox.Docking.Api.Units;

namespace ToolboxAddinExamples.Qsar
{
    public class TbQsarAddinFactory : ITbQsarFactory, ITbObjectFactoryDomain
    {
        //private fields
        private QsarDescriptorInfo _logKowDescriptor;

        private readonly TbUnit _calcUnit;

        private TbUnit _logKowTbUnit;

        //public properties
        public TbObjectFlags Flags { get; }

        public QsarFlags QsarFlags => QsarFlags.None;

        public TbObjectId ObjectId { get; }

        public TbObjectAbout ObjectAbout { get; }

        public string ClientDomainExplainer => null;
        
        public TbMetadata Metadata { get; }

        public string AgreementInfo => null;

        public string ReportDisclaimer => null;

        public IReadOnlyList<string> EndpointLocation { get; }

        public TbScale ScaleDeclaration { get; }

        public IReadOnlyList<QsarDescriptorInfo> XDescriptors { get; private set; }

        public string QmrfLocation { get; private set; }

        public TbQsarStatistics Statistics => QsarAddinDefinitions.M4RatioModelStatistics;

        public TbQsarAddinFactory()
        {
            //The MUST preliminary initialize properties of IObjectFactory
            Flags = TbObjectFlags.None;
            ObjectId = new TbObjectId("(Test) LC50 PP", new Guid("1741bb1a-e231-4e79-93e8-702c3c4dc1ef"), new Version(1, 0));
            ObjectAbout = QsarAddinDefinitions.GetM4ObjectAbout();

            EndpointLocation = QsarAddinDefinitions.AquaticToxicityEndpointLocation;

            var durationTbData = QsarAddinDefinitions.GetDurationKeyValuePair(96, "h");
            Metadata = new TbMetadata(QsarAddinDefinitions.PimephalesLc50MetaDataValues, new Dictionary<string, TbData>() { { durationTbData.Item1, durationTbData.Item2 } });
            
            ScaleDeclaration = new TbRatioScale(TbScale.MolarConcentration, QsarAddinDefinitions.Log1OverMolPerLitreString);
            _calcUnit = new TbUnit(ScaleDeclaration.Name, QsarAddinDefinitions.Log1OverMolPerLitreString);
        }

        public bool InitFactory(IList<string> errorLog, ITbInitTask initTask)
        {
            //QMRF
            QmrfLocation = "http://oasis-lmc.org/";

            //X descriptors
            var logKowCalculator = initTask.ObjectCatalog.Calculators.FirstOrDefault(c => c.Caption.Equals(QsarAddinDefinitions.LogKow, StringComparison.InvariantCultureIgnoreCase));
            if (logKowCalculator == null)
                throw new Exception("The log Kow calculator has not been found in Toolbox.");
            var calcInfo = initTask.ObjectCatalog.GetCalculatorInfo(logKowCalculator, initTask);
            var logKowTaskFamily = initTask.ObjectCatalog.GetAllScales().FirstOrDefault(s => s.Name == calcInfo.Unit.FamilyName);
            if (logKowTaskFamily == null)
                throw new Exception("The family of log Kow has not been found in Toolbox.");
            _logKowDescriptor = new QsarDescriptorInfo(logKowCalculator, logKowTaskFamily);
            _logKowTbUnit = calcInfo.Unit;
            XDescriptors = new List<QsarDescriptorInfo>() { _logKowDescriptor };
            return true;
        }

        public IReadOnlyList<ChemicalWithData> TrainingSet(ITbWorkTask task)
        {
            return QsarAddinDefinitions.GetM4TrainingSet(_calcUnit, _logKowTbUnit);
        }

        public IReadOnlyList<ChemicalWithData> GetTestSet(ITbWorkTask task)
        {
            return QsarAddinDefinitions.GetM4TestSet(_calcUnit, _logKowTbUnit);
        }

        public ITbQsar GetQsar(ITbWorkTask task)
        {
            return new QsarAddin(_logKowDescriptor, _calcUnit);
        }
    }
}
