// Created with MonoDevelop
//
//    Copyright (C) 2024 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 Hiperscan.Unix;
using Hiperscan.Spectroscopy;

using Hiperscan.Spectroscopy.Processing;

namespace Hiperscan.Spectroscopy.ReferenceChecks
{
    public partial class ReferenceChecks
    {
        public BlackReferenceCheckResult CheckBlackReference(Spectrum spectrum, bool throw_exception = true)
        {
            if (this.PlausibilityChecks == false)
                return new BlackReferenceCheckResult(true, spectrum, null, this.SpectrumProcessor.InstrumentReferenceSystem, double.NaN, double.NaN);

            switch (spectrum.ProbeType)
            {
                case ProbeType.Unknown:
                case ProbeType.FinderStandard:
                case ProbeType.FinderSDStandard:
                case ProbeType.FinderSDSampleSpinner:
                    return this.CheckStandardBlackReference(spectrum, throw_exception);

                case ProbeType.FinderXStandard:
                case ProbeType.FinderXLineScan:
                    return this.CheckFix2GlassBlackReference(spectrum, throw_exception);

                default:
                    Exception ex = new Exception(string.Format(Catalog.GetString("Not supported Probe Type: {0}"), spectrum.ProbeType));
                    if (throw_exception)
                        throw ex;
                    return new BlackReferenceCheckResult(false, spectrum, ex, this.SpectrumProcessor.InstrumentReferenceSystem, double.NaN, double.NaN);
            }
        }

        public BlackReferenceCheckResult CheckStandardBlackReference(Spectrum spectrum, bool throw_exception = true)
        {
            return this.CheckBlackReference(spectrum, ReferenceChecks.EXTERNAL_BLACK_INTENSITY_MEAN_THRESHOLD, throw_exception);
        }

        public BlackReferenceCheckResult CheckFix2GlassBlackReference(Spectrum spectrum, bool throw_exception = true)
        {
            return this.CheckBlackReference(spectrum, ReferenceChecks.FIX2GLASS_BLACK_REFERENCE_MEAN_THRESHOLD, throw_exception);
        }

        public BlackReferenceCheckResult CheckBlackReference(Spectrum spectrum, double intensity_mean_threshold, bool throw_exception = true)
        {
            if (this.PlausibilityChecks == false)
                return new BlackReferenceCheckResult(true, spectrum, null, this.SpectrumProcessor.InstrumentReferenceSystem, double.NaN, double.NaN);

            double intensity_mean = spectrum.Intensity.YMean();

            bool is_referenceblock = this.SpectrumProcessor.InstrumentReferenceSystem == InstrumentReferenceSystem.ReferenceBlock;

            if (intensity_mean > intensity_mean_threshold)
            {
                this.SaveReferenceMethod?.Invoke(spectrum, 
                                                 is_referenceblock ? SpectrumType.Fix2GlassBlack : SpectrumType.ExternalEmpty, 
                                                 true, 
                                                 string.Empty);

                if (this.CallFailureMethod)
                    this.FailureMethod?.Invoke();

                BlackReferenceException ex = new BlackReferenceException(Catalog.GetString("Please check the black reference as well as the black distance ring and repeat measurement."));

                if (throw_exception)
                    throw ex;
                else
                    return new BlackReferenceCheckResult(false, 
                                                         spectrum, 
                                                         ex, 
                                                         this.SpectrumProcessor.InstrumentReferenceSystem, 
                                                         intensity_mean, 
                                                         intensity_mean_threshold);
            }

            return new BlackReferenceCheckResult(true,
                                                 spectrum,
                                                 null,
                                                 this.SpectrumProcessor.InstrumentReferenceSystem,
                                                 intensity_mean,
                                                 intensity_mean_threshold); 
        }
    }
}
