// 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 SampleSpinnerWhiteReferenceCheckResult CheckSampleSpinnerWhiteReference(Spectrum spectrum, bool throw_exception = true)
        {
            double correlation_threshold = ReferenceChecks.EXTERNAL_WHITE_CORRELATION_THRESHOLD_SAMPLE_SPINNER;
            if (this.SpectrumProcessor.ReferenceWheelVersion == ReferenceWheelVersion.TitaniumDioxide)
                correlation_threshold = ReferenceChecks.EXTERNAL_WHITE_CORRELATION_THRESHOLD_TIO2;

            double intensity_mean_threshold = ReferenceChecks.EXTERNAL_WHITE_INTENSITY_MEAN_THRESHOLD_SAMPLE_SPINNER;

            return this.CheckSampleSpinnerWhiteReference(spectrum, correlation_threshold, intensity_mean_threshold, throw_exception);
        }

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

            if (this.SpectrumProcessor.InstrumentReferenceSystem != InstrumentReferenceSystem.ReferenceWheel)
                throw new Exception(Catalog.GetString("Cannot check reference. Invalid reference type."));

            ReferenceWheelProcessor processor = (ReferenceWheelProcessor)this.SpectrumProcessor;

            DataSet ds = new DataSet(spectrum.RawIntensity.Y, processor.InternalWhite.RawIntensity.Y);
            double correlation = ds.Corr();

            if (throw_exception)
                Console.WriteLine("White Reference (Standard) correlation: " + correlation.ToString());

            double intensity_mean = spectrum.Intensity.YMean();
            double intensity_max = spectrum.Intensity.YMax();

            if (correlation < correlation_threshold && this.UseCorrelation ||
                intensity_mean < intensity_mean_threshold)
            {
                this.SaveReferenceMethod?.Invoke(spectrum, SpectrumType.ExternalWhite, true, string.Empty);

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

                WhiteReferenceException ex = new WhiteReferenceException(Catalog.GetString("Please check the white reference with sample insert as well as the black distance ring and repeat the measurement."));

                if (throw_exception)
                    throw ex;
                else
                    return new SampleSpinnerWhiteReferenceCheckResult(false,
                                                                     spectrum,
                                                                     ex,
                                                                     processor.InstrumentReferenceSystem,
                                                                     processor.InternalWhite,
                                                                     ds,
                                                                     correlation,
                                                                     correlation_threshold,
                                                                     intensity_mean,
                                                                     intensity_mean_threshold);
            }

            return new SampleSpinnerWhiteReferenceCheckResult(false,
                                                             spectrum,
                                                             null,
                                                             processor.InstrumentReferenceSystem,
                                                             processor.InternalWhite,
                                                             ds,
                                                             correlation,
                                                             correlation_threshold,
                                                             intensity_mean,
                                                             intensity_mean_threshold);
        }
    }
}
