// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2017 Thomas Klose & 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.IO;
using System.Text;
using Hiperscan.AnalysisModule;
using Hiperscan.AnalysisModule.Authentification;
using Hiperscan.AnalysisModule.Identification.ValidationReportInfo;
using Hiperscan.ApoIdentCore.SectionManager.Measuring;
using Hiperscan.ApoIdentCore.SectionManager.Pharmacy;
using Hiperscan.ApoIdentCore.SectionManager.Result;
using Hiperscan.ApoIdentCore.SectionManager.Specimen;
using Hiperscan.ApoIdentCore.SectionManager.Substance;
using Hiperscan.Common.I18n;
using Hiperscan.Common.IO;
using Hiperscan.ApoIdentCommon.ApoConfig;
using Hiperscan.ApoIdentCommon.ApoConfig.Enums;
using Hiperscan.ApoIdentCommon.ApoConfig.ThirdPartyDataExchange;
using Hiperscan.SGS.Benchtop.Transformations;
using Hiperscan.Spectroscopy;
using Hiperscan.Unix;

namespace Hiperscan.ApoIdentCore.Reporting.ReportData
{
    public partial class ReportInfo
    {
        private const string QUERY_TAG = "QueryMetaData";
        public const string USE_ZENITH = "Zenith";
        public const string VERSION = "3.0";

        public ReportInfo()
        {
        }

        public ReportInfo(AppControl control)
        {
            this.SetPharmacyData(control.PharmacyManager);
            this.SetProfileData(control.ProfileManager);
            this.SetSubstanceData(control.SubstanceManager, control.ProfileManager.CurrentProfile.PrintValidationWhitinProtocol);
            this.SetSpecimenData(control.SpecimenManager);
            this.SetMeasuringData(control.MeasuringManager);
            this.SetRsultData(control.ResultManager);

            this.SetFooter(control);
            this.SetFileNames(control.ProfileManager);
            this.SetReportInfo();
        }

        private void SetProfileData(ProfileManager profile_manager)
        {
            this.Company = profile_manager.CurrentProfile.Company;
            this.Town = profile_manager.CurrentProfile.Town;
            this.Street = profile_manager.CurrentProfile.Street;
            this.ReportCountry = profile_manager.CurrentProfile.ReportCountry;
            this.ProtocolType = profile_manager.CurrentProfile.ExchangeData.ProtocolType;
            this.ShowDifferencePlot = profile_manager.CurrentProfile.ShowDifference;
            this.BAKMarkingActivated = profile_manager.CurrentProfile.BakMarking.IsActive &&
                profile_manager.CurrentProfile.IsBakMarkingUsable;
            this.CertificationControl = profile_manager.CurrentProfile.CertificationControl;
        }

        private void SetPharmacyData(PharmacyManager pharmacy_manager)
        {
            this.Operator = pharmacy_manager.Operator.GetEntryValue();
        }

        private void SetSubstanceData(SubstanceManager substance_manager, bool print_validation_report)
        {
            this.DefaultName = substance_manager.SubstancesCatalog.Substance.PrimaryDefaultName;
            this.LatinName = substance_manager.SubstancesCatalog.Substance.PrimaryLatinName;
            this.SelectedName = substance_manager.SubstancesCatalog.SelectedSubstanceName;
            this.SubstanceTradeName = substance_manager.SubstancesCatalog.SubstanceTradeName;
            this.SubstanceClass = substance_manager.SubstancesCatalog.ModelClass.Name;
            this.AccessDatabaseType = substance_manager.SubstancesCatalog.ModelClass.DatabaseInfo.DatabaseType;
            this.SelectedSubstanceId = substance_manager.SubstancesCatalog.Substance.Id;
            this.ClassificationName = substance_manager.SubstancesCatalog.Classification.Name;
            this.ClassificationType = substance_manager.SubstancesCatalog.Classification.ClassificationType;
            this.HasValidationDocument = substance_manager.SubstancesCatalog.ModelClass.HasValidationDocument;
            this.IsMeasurable = substance_manager.SubstancesCatalog.Classification.IsNirMeasurable;
            this.SubstanceNamesOfClassification = new List<string>(substance_manager.SubstancesCatalog.Classification.GetSubstanceNames().Keys);
            this.ServerLocation = CatalogLocale.GetLocaleType();
            this.BAKMarking = substance_manager.BakMarking.GetEntryValue();
            this.Synonyms = substance_manager.SubstancesCatalog.Substance.GetSynonyms(new HashSet<string>(new string[] { this.SelectedName }));

            if (substance_manager.SubstancesCatalog.IsSelectedSubstanceNirMeasurable)
            {
                this.AnalysisModuleVersion = substance_manager.CurrentServerInfo.Version.ModuleVersion;

                if (print_validation_report)
                    this.ValidationReportInfo = substance_manager.SubstancesCatalog.Classification.ReportInfo;
            }
        }

        private void SetSpecimenData(SpecimenManager specimen_manager)
        {
            this.Ppn = specimen_manager.PPN.GetEntryValue();
            this.Producer = specimen_manager.Producer.GetEntryValue();
            this.Batch = specimen_manager.Batch.GetEntryValue();
            this.ReferenceQuantityValue = specimen_manager.ReferenceQuantity.GetEntryValue().QuantityValue;
            this.ReferenceQuantityUnit = specimen_manager.ReferenceQuantity.GetEntryValue().QuatityUnit;
            this.Distributor = specimen_manager.Distributor.GetEntryValue();
            this.ExpireDate = specimen_manager.ExpiryDate.DateTimeValue;
            this.GracePeriodValue = specimen_manager.GracePeriod.GetEntryValue().QuantityValue;
            this.GracePeriodUnit = specimen_manager.GracePeriod.GetEntryValue().QuantityUnit;
            this.CorrectionFactor = specimen_manager.CorrectionFactor.GetEntryValue();
            this.DeliveryDate = specimen_manager.DeliveryDate.DateTimeValue;
            this.PriceValue = specimen_manager.Price.GetEntryValue();
            this.PriceUnit = specimen_manager.Price.Currency;
            this.THCInput = specimen_manager.THC.GetEntryValue();
            this.CBDInput = specimen_manager.CBD.GetEntryValue();
            this.Variety = specimen_manager.Variety.GetEntryValue();
        }

        private void SetMeasuringData(MeasuringManager measuring_manager)
        {
            if (measuring_manager.IsNirMeasurable)
            {
                this.DimmerValue = measuring_manager.Finder.DimmerValue;
                this.WhiteReference = ReportInfo.USE_ZENITH;
                this.ScanEngineVersion = measuring_manager.Finder.ScanEngineVersion;
                this.Serial = measuring_manager.Finder.Serial;
                this.DeviceName = measuring_manager.Finder.DeviceName;
                this.OemSerialNumber = measuring_manager.Finder.OemSerialNumber;
                this.FinderSDTransformation = measuring_manager.Finder.Current.TransformationType;
                this.TestId = measuring_manager.GetMeasurmentId();
                this.Creator = measuring_manager.ProcessedSpectrum.Creator;
                this.Spectrum = measuring_manager.ProcessedSpectrum;
                this.ProbeType = measuring_manager.ProcessedSpectrum.ProbeType;
                this.SpectrumType = measuring_manager.ProcessedSpectrum.SpectrumType;
                this.Date = measuring_manager.ProcessedSpectrum.Timestamp;

                if (String.IsNullOrEmpty(this.OemSerialNumber) == true)
                    this.OemSerialNumber = this.Serial;

                this.DeviceConnectionType = String.Format("{0} | {1}",
                                                          measuring_manager.Finder.ProductName,
                                                          measuring_manager.Finder.ConnectionType);

                if (measuring_manager.Finder.Device.Info.IsRemote == true)
                    this.DeviceConnectionType += " - " + measuring_manager.Finder.RemoteDeviceServerAddress;
            }
            else
            {
                this.Date = measuring_manager.NotMeasurableDate;
                this.TestId = measuring_manager.GetMeasurmentId();
            }
        }

        private void SetRsultData(ResultManager result_manager)
        {
            this.AnalysisType = result_manager.AnalysisType;
            this.AnalysisMethodVersion = String.Empty;

            if (result_manager.IsNirMeasurable)
            {
                if (result_manager.AnalysisType == AnalysisType.Identification)
                {
                    this.Version = result_manager.IdentificationResult.Identifier + " (" + result_manager.IdentificationResult.Date.ToString("yyyy-MM-dd hh:mm") + ")";
                    this.Rating = result_manager.IdentificationResult.Rating;
                    this.MinRating = result_manager.IdentificationResult.MinRating;
                    this.MatchId = result_manager.IdentificationResult.MatchId;
                    this.MatchRating = result_manager.IdentificationResult.MatchRating;
                    this.IsMatch = result_manager.IdentificationIsTruePositive;
                    this.MatchBackProjection = result_manager.IdentificationResult.MatchBackProjection;
                    this.Backprojection = result_manager.IdentificationResult.SpectrumBackProjection;
                    this.AnalysisMethodVersion = result_manager.IdentificationResult.AnalysisMethodeVersion;

                }
                else
                {
                    this.RawTHCResult = result_manager.QuantificationResult.RawTHCResult;
                    this.RawCBDResult = result_manager.QuantificationResult.RawCBDResult;
                    this.CannabisResult = result_manager.QuantificationResult;
                    this.CannabisClassification = result_manager.QuantificationResult.GetCannabisClassification();
                    this.CannabisResultIsTrustable = result_manager.QuantificationResult.IsTrustable;
                    this.AnalysisMethodVersion = result_manager.QuantificationResult.AnalysisMethodeVersion;

                    this.CBDModelId = CannabisResult.CBD_ID;
                    this.THCModelId = CannabisResult.THC_ID;
                }
            }
            else
            {
                this.IsMatch = false;
            }

            this.Comment = result_manager.Comment.GetEntryValue();
            this.AdditionalTest = result_manager.CurrentAdditionalTest.ProtocolText;
            this.CustomerResult = result_manager.CurrentAdditionalTest.ProtocolCustomerEvaluation;
            this.HasCustomerResult = result_manager.CurrentAdditionalTest.InsertIntoProtocol;
        }

        private void SetFooter(AppControl control)
        {
            if (this.IsMeasurable == true)
            {
                AnalysisServerInfo info = control.SubstanceManager.CurrentServerInfo;

                this.Footer = String.Format(Catalog.GetString("Created by QuickStep {0} {1} ,{2} {3}, SGS: {4}, White reference: {5}, {6}, {7}, https://www.hiperscan.com"),
                                        ApoIdentInfo.NAME,
                                        ApoIdentInfo.FullVersion,
                                        control.SubstanceManager.SubstancesCatalog.AnalysisType.GetProductName(),
                                        info.Version.ModuleVersion,
                                        control.MeasuringManager.Finder.Serial,
                                        "Zenith",
                                        info.ModelTypeInfo,
                                        ApoIdentInfo.COPYRIGHT);
            }
            else
            {
                this.Footer = String.Format(Catalog.GetString("Created by QuickStep {0} {1}, {2}, http://www.hiperscan.com"),
                                            ApoIdentInfo.NAME,
                                            ApoIdentInfo.FullVersion,
                                            ApoIdentInfo.COPYRIGHT);
            }
        }

        private void SetFileNames(ProfileManager profile_manager)
        {
            this.PdfFileFullName = this.ProtocolPdfFileName((profile_manager));
            this.XmlFileFulleName = this.ProtocolXmlFileName((profile_manager));
            if (this.IsMeasurable == true)
                this.CsvFilFullName = this.ProtocolCsvFileName((profile_manager));
        }

        private void SetReportInfo()
        {
            if (this.Spectrum == null)
                return;

            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("[Apo-Ident::SubstanceClass]{0}\n", this.SubstanceClass);
            sb.AppendFormat("[Apo-Ident::Specimen]{0}\n", this.DefaultName);
            sb.AppendFormat("[Apo-Ident::Latin]{0}\n", this.LatinName);
            sb.AppendFormat("[Apo-Ident::Batch]{0}\n", this.Batch);
            sb.AppendFormat("[Apo-Ident::Pzn]{0}\n", this.Ppn);
            sb.AppendFormat("[Apo-Ident::Supplier]{0}\n", this.Distributor);
            sb.AppendFormat("[Apo-Ident::ExpireDate]{0}\n", this.ExpireDate.ToString("yyyy-MM-dd"));

            sb.AppendFormat("[Apo-Ident::DeviceName]{0}\n", this.DeviceName);
            sb.AppendFormat("[Apo-Ident::DimmerValue]{0}\n", this.DimmerValue.ToString());
            sb.AppendFormat("[Apo-Ident::ScanEngineVersion]{0}\n", this.ScanEngineVersion);
            sb.AppendFormat("[Apo-Ident::DeviceConnectionType]{0}\n", this.DeviceConnectionType);

            sb.AppendFormat("[Apo-Ident::TestId]{0}\n", this.TestId);
            sb.AppendFormat("[Apo-Ident::User]{0}\n", this.Operator);
            sb.AppendFormat("[Apo-Ident::Comment]{0}\n", this.Comment);

            sb.AppendFormat("[Apo-Ident::SelectedSubstanceId]{0}\n", this.SelectedSubstanceId);
            if (this.AnalysisType == AnalysisType.Identification)
            {
                sb.AppendFormat("[Apo-Ident::IsMatch]{0}\n", this.IsMatch.ToString());
                sb.AppendFormat("[Apo-Ident::Confidence]{0}\n", this.Rating.ToString(Spectrum.CultureInfo));
                sb.AppendFormat("[Apo-Ident::MinRating]{0}\n", this.MinRating.ToString(Spectrum.CultureInfo));
                sb.AppendFormat("[Apo-Ident::MatchName]{0}\n", this.MatchId);
                sb.AppendFormat("[Apo-Ident::MatchRating]{0}\n", this.MatchRating.ToString(Spectrum.CultureInfo));
                sb.AppendFormat("[Apo-Ident::CustomerEval]{0}\n", this.CustomerResult.ToString());
            }
            else
            {
                sb.AppendFormat("[Apo-Ident:THCId]{0}\n", CannabisResult.THC_ID);
                sb.AppendFormat("[Apo-Ident:THCInput]{0}\n", this.THCInput);
                sb.AppendFormat("[Apo-Ident:THCResult]{0}\n", this.RawTHCResult.ToString(Spectrum.CultureInfo));
                sb.AppendFormat("[Apo-Ident:CBDId]{0}\n", CannabisResult.CBD_ID);
                sb.AppendFormat("[Apo-Ident:CBDInput]{0}\n", this.CBDInput);
                sb.AppendFormat("[Apo-Ident:CBDResult]{0}\n", this.RawCBDResult.ToString(Spectrum.CultureInfo));
            }


            sb.AppendFormat("[Apo-Ident::Version]{0}\n", this.Version);
            sb.AppendFormat("[Apo-Ident::AnalysisMethodVersion]{0}\n", this.AnalysisMethodVersion);
            sb.AppendFormat("[Apo-Ident::WhiteReference]{0}\n", this.WhiteReference);
            sb.AppendFormat("[Apo-Ident::FinderSDTransformation]{0}", this.FinderSDTransformation.ToString());

            this.Spectrum.Comment = sb.ToString();
        }

        private string GetProtocolNameWithoutFileExtension(ProfileManager profile_manager)
        {
            string specimen = this.DefaultName;

            if (String.IsNullOrEmpty(this.LatinName) == false)
            {
                if (profile_manager.CurrentProfile.FileNameStart == FilenameStartTypes.LatinName)
                    specimen = this.LatinName;
            }

            if (specimen.Length > 10)
                specimen = specimen.Remove(10);

            return FileIOHelper.ConvertToValidFilename(
                specimen + "__" + this.Batch + "__" + this.Date.ToString("yyyy-MM-dd_HH-mm-ss"));
        }

        public string ProtocolCsvFileName(ProfileManager profile_manager)
        {
            return Path.Combine(profile_manager.CurrentProfile.ArchiveYearDir,
                                this.GetProtocolNameWithoutFileExtension(profile_manager) + ".csv");
        }

        public string ProtocolPdfFileName(ProfileManager profile_manager)
        {
            return Path.Combine(profile_manager.CurrentProfile.ArchiveYearDir,
                                this.GetProtocolNameWithoutFileExtension(profile_manager) + ".pdf");
        }

        public string ProtocolXmlFileName(ProfileManager profile_manager)
        {
            return Path.Combine(profile_manager.CurrentProfile.ArchiveQueryDir,
                                this.GetProtocolNameWithoutFileExtension(profile_manager) + ".xml");
        }

        public string Serial { get; set; } = String.Empty; //OK
        public string DeviceName { get; set; } = String.Empty; //OK
        public string OemSerialNumber { get; set; } = String.Empty; //OK
        public byte DimmerValue { get; set; } = 0; //OK
        public string ScanEngineVersion { get; set; } = Catalog.GetString("n/a"); //OK
        public string DeviceConnectionType { get; set; } = String.Empty;

        public string SelectedSubstanceId { get; set; } = String.Empty;
        public double Rating { get; set; } = 0;
        public double MinRating { get; set; } = 0;
        public string MatchId { get; set; } = String.Empty;
        public double MatchRating { get; set; } = 0;

        public string AdditionalTest { get; set; } = String.Empty;

        public string Footer { get; set; } = String.Empty;
        public string Version { get; set; } = String.Empty;
        public string AnalysisMethodVersion { get; set; } = String.Empty;
        public string WhiteReference { get; set; } = String.Empty;
        public string AnalysisModuleVersion { get; set; } = String.Empty;
        public string Creator { get; set; } = String.Empty;

        public ProbeType ProbeType { get; set; } = ProbeType.Unknown;
        public ProtocolType ProtocolType { get; set; } = ProtocolType.ApoIdent;
        public SpectrumType SpectrumType { get; set; } = SpectrumType.Unknown;
        public AccessDatabaseType AccessDatabaseType { get; set; } = AccessDatabaseType.None;
        public string ClassificationName { get; set; } = String.Empty;
        public bool HasValidationDocument { get; set; } = false;

        public HashSet<string> Synonyms { get; set; } = new HashSet<string>();
        public List<string> SubstanceNamesOfClassification { get; set; } = new List<string>();
        public bool ShowDifferencePlot { get; set; } = false;
        public string ReportInfoVersion { get; set; } = ReportInfo.VERSION;
        public CatalogLocale.LocaleType ServerLocation { get; set; } = CatalogLocale.LocaleType.Unknown;

        public TransformationTypes FinderSDTransformation { get; set; } = TransformationTypes.None;
        public ClassificationReportInfo ValidationReportInfo { get; set; } = null;

        public Spectrum Spectrum { get; set; } = null;
        public DataSet MatchBackProjection { get; set; } = null;
        public DataSet Backprojection { get; set; } = null;
        public string PdfFileFullName { get; set; } = String.Empty;
        public string CsvFilFullName { get; set; } = String.Empty;
        public string XmlFileFulleName { get; set; } = String.Empty;

        public CannabisResult CannabisResult { get; set; }

        public string THCModelId { get; set; }
        public string CBDModelId { get; set; }

        public bool CertificationControl { get; set; }
    }
}


