// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2021 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.Linq;
using Hiperscan.AnalysisModule.Authentification;
using Hiperscan.AnalysisModule.Identification;
using Hiperscan.AnalysisModule;

namespace Hiperscan.ApoIdentCore.SectionManager.Substance.SubstanceSelection
{
    public partial class SubstancesCatalog
    {
        public delegate void ErrorHandler(string info);

        public event EventHandler SubstanceSelectionChanged = null;
        public event EventHandler SeveralModelClassesDetected = null;
        public event EventHandler MultipleClassificationDetected = null;

        public event EventHandler BeginSubstanceSelection = null;
        public event EventHandler SubstanceSelectionAborted = null;

        public event EventHandler SubstanceSelectionStateChanged = null;
        public event EventHandler SubstanceMeasurableStateChanged = null;

        public SubstancesCatalog()
        {
            this.Reset();
            this.Resolver = new SubstanceResolver();
        }

        public void Clear()
        {
            this.Reset();
            this.Resolver.Clear();
        }

        public void Reset()
        {
            this.PreselectedSubstances = new List<IdentSubstance>();
            this.FuzzyName = String.Empty;

            this.SelectionType = SubstanceSelectionType.None;
            this.Substance = null;
            this.Classification = null;
            this.ModelClass = null;

            this.SelectedSubstanceName = String.Empty;
            this.SelectedDefaultName = String.Empty;
            this.SelectedLatinName = String.Empty;
            this.ClassificationType = ClassificationType.None;
            this.Synonnyms = new HashSet<string>();
            this.SubstanceTradeName = String.Empty;
            this.ExchangeData = null;
            this.IsSubstanceSelected = false;
            this.AnalysisType = AnalysisType.None;
        }

        public void AddModelClass(IdentModelClass model_class)
        {
            if (model_class.DatabaseInfo.DatabaseType == AccessDatabaseType.UserDefined)
            {
                this.NotMeasurableModelClassFromServer = model_class;
                return;
            }

            this.Resolver.AddModelClass(model_class);
        }

        public void RefreshUserDefinedSubstances(IdentModelClass other_user_model)
        {
            this.Resolver.RemoveUserdefinedModelClass();

            if (other_user_model == null)
                return;

            if (other_user_model.DatabaseInfo.DatabaseType != AccessDatabaseType.UserDefined)
                return;

            if (other_user_model == null || other_user_model.Classifications.Count == 0)
                return;

            other_user_model.InitResolver();
            int visibles_count = other_user_model.Classifications.SelectMany(x => x.Substances).
                                                       Where(x => x.IsVisible).
                                                       Count();

            if (visibles_count == 0)
                return;

            this.Resolver.AddModelClass(other_user_model);
        }

        public void ChangeModelClass()
        {
            if (this.IsPreselectionUnique == true)
                return;

            if (this.IsProtocolSaved() == false)
            {
                this.SubstanceSelectionAborted?.Invoke(this, EventArgs.Empty);
                return;
            }

            this.SeveralModelClassesDetected?.Invoke(this, EventArgs.Empty);
            IdentSubstance substance = this.PreselectedSubstances.First(item => item.FromUserSelected);
           
            this.SetNewSubstance(substance);
        }

        public void ShowSubstanceInfo()
        {
            this.MultipleClassificationDetected?.Invoke(this, EventArgs.Empty);
        }

        public List<SubstanceListAutoCompletionEntry> AutoCompletionEntries
        {
            get
            {
                return this.Resolver.AutoCompletionEntries;
            }
        }

        public void ResetUserSelections()
        {
            foreach (IdentSubstance subsbstance in this.PreselectedSubstances)
                subsbstance.FromUserSelected = false;
        }

        public void SortPreselectedSubstanceByFuzzyName()
        {
            this.PreselectedSubstances = this.PreselectedSubstances.
                OrderBy(item => item.BestReferenceName).
                ToList();
        }

        public void SortPreselectedSubstanceByCategory()
        {
            this.PreselectedSubstances = this.PreselectedSubstances.
                OrderBy(item => item.Classification.ClassificationType).
                ToList();
        }

        public bool IsPreselectionUnique
        {
            get
            {
                return this.PreselectedSubstances.Count < 2;
            }
        }

        public bool IsYellowSubstance
        {
            get
            {
                return this.ClassificationType == ClassificationType.Multiple;
            }
        }

        public HashSet<string> AllSubstanceNames
        {
            get
            {
                return this.Resolver.AllSubstanceNames;
            }
        }

        public List<IdentModelClass> AllModelClasses
        {
            get
            {
                return this.Resolver.AllModelClasses;
            }
        }

        public List<IdentModelClass> MasterModelClasses
        {
            get
            {
                return this.Resolver.MasterModelClasses;
            }
        }

        public List<IdentModelClass> ValidationDocuModelClasses
        {
            get
            {
                return this.AllModelClasses.Where(m => m.HasValidationDocument).ToList();
            }
        }

        public List<IdentModelClass> AdditionalTestModelClasses
        {
            get
            {
                return this.AllModelClasses.Where(m => m.HasAdditionalTestDocument).ToList();
            }
        }

        public List<IdentModelClass> SubstanceDocuModelClasses
        {
            get
            {
                return this.AllModelClasses.Where(m => m.DatabaseInfo.AnyalysisType == AnalysisType.Identification).ToList();
            }
        }

        private IdentModelClass not_measurable_model_class_from_server = null;
        public IdentModelClass NotMeasurableModelClassFromServer
        {
            get
            {
                return this.not_measurable_model_class_from_server?.Clone();
            }
            private set
            {
                this.not_measurable_model_class_from_server = value;
            }
        }

        public bool ContinueAction { get; set; } = false;
        private SubstanceResolver Resolver { get; set; }
    }
}
