using System.Collections.Generic;
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 QsarAddin : ITbQsar, ITbObjectDomain
    {
        private readonly QsarDescriptorInfo _logKowDescriptor;
        private readonly TbUnit _qsarUnit;

        public QsarAddin(QsarDescriptorInfo logKowDescriptor, TbUnit qsarUnit)
        {
            _logKowDescriptor = logKowDescriptor;
            _qsarUnit = qsarUnit;
        }

        public void Dispose()
        {
        }

        public TbScalarData Calculate(ITbBasket target)
        {
            var targetLogKow =
                target.WorkTask.CalcService.CalculateParameter(_logKowDescriptor.Descriptor, null, target);

            //throw if task is canceled to not return wrong results
            target.WorkTask.TbToken.ThrowIfCancellationRequested();

            if (targetLogKow?.Value == null)
                return null;
            var predictedValue = -2.16 - 0.723 * targetLogKow.Value.Value;
            return new TbScalarData(_qsarUnit, predictedValue);
        }

        public ITbPrediction Predict(ITbBasket target)
        {
            var predictedScalarData = Calculate(target);

            var predictedTbData = new TbData(predictedScalarData.Unit, predictedScalarData.Value);
            var targetLogKow =
                target.WorkTask.CalcService.CalculateParameter(_logKowDescriptor.Descriptor, null, target);
            var xData = new Dictionary<TbObjectId, TbData>
            {
                {_logKowDescriptor.Descriptor, new TbData(targetLogKow.Unit, targetLogKow.Value)}
            };
            //optional
            var predictionDescription =
                new TbMetadata(new Dictionary<string, string> {{"Description", "API prediction"}}, null);
            return new PredictionAddin(predictedTbData, predictionDescription, xData);
        }

        public bool IsRelevantToChemical(ITbBasket chemical, out string reason)
        {
            reason = null;
            return true;
        }
        
        public TbDomainStatus CheckDomain(ITbBasket basket)
        {
            var chemLogKow = basket.WorkTask.CalcService.CalculateParameter(_logKowDescriptor.Descriptor, null, basket);
            if (chemLogKow?.Value == null)
                return TbDomainStatus.Undefined;
            if (chemLogKow.Value.Value > -1.31 && chemLogKow.Value.Value < 6.2)
                return TbDomainStatus.InDomain;
            return TbDomainStatus.OutOfDomain;
        }
    }
}
