// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2022, 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.Globalization;
using System.Linq;
using System.Reflection;
using Hiperscan.Unix;
using Hiperscan.ApoIdentCore.SectionManager.Substance.SubstanceSelection;
using Hiperscan.ApoIdentCore.SectionManager.Specimen.Fields;
using Hiperscan.ApoIdentCore.SectionManager.FieldDefinitions;
using Hiperscan.ApoIdentCore.Misc;
using Hiperscan.ApoIdentCommon.ApoConfig;
using Hiperscan.ApoIdentCommon.ApoConfig.Enums;
using Hiperscan.ApoIdentCommon.ApoConfig.Internationalization;

namespace Hiperscan.ApoIdentCore.SectionManager.Specimen
{
    public class SpecimenManager : ISectionManager
    {
        public event EventHandler CompleteStateChanged = null;

        public SpecimenManager(ProfileManager profile_manager, GlobalStates states)
        {
            this.ProfileManager = profile_manager;
            this.GlobalStates = states;

            foreach (PropertyInfo property in this.GetType().GetProperties())
            {
                IInputField input_field = property.GetValue(this) as IInputField;
                if (input_field != null)
                    this.AllFields.Add(input_field);
            }

            this.SetCurrency();
        }

        public void SetValidStateChangedEvents(EventHandler handler)
        {
            foreach (IInputField input_field in this.AllFields)
            {
                input_field.ValidStateChanged += handler;
                input_field.ValidStateChanged += (sender, e) => this.SetCompletedState();
            }
        }

        public void SetValueChangedEvents(EventHandler handler)
        {
            foreach (IInputField input_field in this.AllFields)
                input_field.ValueChanged += handler;
        }

        public void SetGracePeriodPluralChangedEvent(EventHandler handler)
        {
            this.GracePeriod.PluralChanged += handler;
        }

        public void UpdateAfterSubstanceSelection(SubstancesCatalog substances_catalog)
        {
            foreach (IInputField input_field in this.AllFields)
                input_field.FireEvent = false;

            if (substances_catalog.SelectionType != SubstanceSelectionType.ThirdParty)
            {
                this.Producer.Entry = substances_catalog.ModelClass.DefaultSupplierName;
                this.GracePeriod.Entry =this.ProfileManager.CurrentProfile.GracePeriod.CurrentValue.Clone();
                this.IsThirdPartyDataExchange = false;
            }
            else
            {
                this.ExpiryDate.Entry = (substances_catalog.ExchangeData.ExpiryDate ?? I18nDateFormat.EmptyDate).ToString("d");
                this.Batch.Entry = substances_catalog.ExchangeData.BatchNumber;
                this.PPN.Entry = substances_catalog.ExchangeData.Ppn;
                this.Producer.Entry = substances_catalog.ExchangeData.Producer;

                if (substances_catalog.ExchangeData.HasWeightCorrFactor)
                    this.CorrectionFactor.Entry = substances_catalog.ExchangeData.WeightCorrFactor;

                this.IsThirdPartyDataExchange = true;
            }

            this.SetVisilibities(substances_catalog);

            foreach (IInputField input_field in this.AllFields)
                input_field.FireEvent = true;

            this.SetCompletedState();
        }

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

        public void Reset()
        {
            foreach (IInputField input_field in this.AllFields)
            {
                input_field.FireEvent = false;
                input_field.SetDefaultValue();
                input_field.FireEvent = true;
            }

            this.SetVisilibities();
            this.IsThirdPartyDataExchange = false;
            this.SetCompletedState();
        }

        public void SetCurrency()
        {
            ReportCountryTypes report_country = I18n.GetDefaultReportCountry();

            if (this.ProfileManager.CurrentProfile != null)
                report_country = this.ProfileManager.CurrentProfile.ReportCountry;

            this.Price.Currency = I18n.GetCurrency(report_country);
        }

        private void SetCompletedState()
        {
            bool value = true;

            if (this.IsThirdPartyDataExchange == false)
            {
                value = this.AllFields.Any(x => x.IsEntryValid == false) == false;
            }


            this.IsComplete = value;
        }

        private void SetVisilibities(SubstancesCatalog catalog = null)
        {
            bool is_quantifier_moode = false;

            if (catalog == null)
            {
                if (this.GlobalStates.IsOnlyQuantifierModuleAvailable)
                    is_quantifier_moode = true;
            }
            else
            {
                is_quantifier_moode = catalog.AnalysisType == AnalysisModule.AnalysisType.Quantification;
            }

            if (is_quantifier_moode)
            {
                this.THC.IsVisible = true;
                this.CBD.IsVisible = true;
                this.Variety.IsVisible = true;
                this.CorrectionFactor.IsVisible = false;
            }
            else
            {
                this.THC.IsVisible = false;
                this.CBD.IsVisible = false;
                this.Variety.IsVisible = false;
                this.CorrectionFactor.IsVisible = true;
            }
        }

        private bool is_complete = false;
        public bool IsComplete
        {
            get
            {
                return this.is_complete;
            }

            private set
            {
                if (this.is_complete == value)
                    return;

                this.is_complete = value;
                this.CompleteStateChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        public List<IInputField> AllFields { get; set; } = new List<IInputField>();

        public PPNField PPN { get; private set; } = new PPNField();
        public ProducerField Producer { get; private set; } = new ProducerField();
        public BatchField Batch { get; private set; } = new BatchField();
        public ReferenceQuantityField ReferenceQuantity { get; private set; } = new ReferenceQuantityField();
        public DistributorField Distributor { get; set; } = new DistributorField();
        public PriceField Price { get; private set; } = new PriceField();
        public ExpiryDateField ExpiryDate { get; private set; } = new ExpiryDateField();
        public GracePeriodField GracePeriod { get; private set; } = new GracePeriodField();
        public CorrectionFactorField CorrectionFactor { get; private set; } = new CorrectionFactorField();
        public DeliveryDateField DeliveryDate { get; private set; } = new DeliveryDateField();
        public THCField THC { get; private set; } = new THCField();
        public CBDField CBD { get; private set; } = new CBDField();
        public VarietyField Variety { get; private set; } = new VarietyField();

        private bool IsThirdPartyDataExchange { get; set; } = false;
        private ProfileManager ProfileManager { get; set; }
        private GlobalStates GlobalStates { get; set; }
 
    }
}
