// 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.Spectroscopy;

namespace Hiperscan.Spectroscopy.Processing
{
    public partial class ReferenceBlockProcessor : SpectrumProcessor
    {
        private Spectrum fix_two_glass_oxide = null;
        private Spectrum dark_reference = null;

        private bool recalc_fix_two_glass_oxide = true;

        public ReferenceBlockProcessor(string creator)
            :base(creator)
        {
            this.InstrumentReferenceSystem              = InstrumentReferenceSystem.ReferenceBlock;
            this.RawSpectrumLimitBandwidthMode          = LimitBandwidthMode.ForcedSwitchOff;
            this.ProcessedSpectrumLimitBandwidthMode    = LimitBandwidthMode.ForcedSwitchOff;
            this.use_default_system_function            = false;
        }

        protected override double IntensityLimit => 0.0001;

        public override Spectrum Process(Spectrum sample_spectrum)
        {
            Spectrum spectrum = sample_spectrum.Clone();
            this.SetSampleRawspectrumData(spectrum);
            spectrum.ApplyCorrectionsToRawData(this.CorrectionMask & ~CorrectionMask.DarkIntensity);

            DataSet intensity = spectrum.RawIntensity - this.ProcessingDark;
            DataSet background = new DataSet(this.ProcessingBackground);

            this.LimitingIntensities(intensity);

            Spectrum processed = this.CreateProcessedSampleSpectrum(spectrum, sample_spectrum, intensity, background);

            if (this.TransformationType != Transformations.TransformationTypes.None)
                this.TransformSpectrum(processed);

            this.ConfigureLimitBandwidth(processed, false);

            return processed;
        }

        protected override void UpdateBlackReference()
        {
            if (this.black_reference != null)
            {
                Spectrum spectrum = this.black_reference.Clone();
                this.SetReferenceRawspectrumData(spectrum);
                spectrum.ApplyCorrectionsToRawData(this.CorrectionMask & ~CorrectionMask.DarkIntensity);

                this.processing_black = spectrum;
            }
            else
                this.processing_black = null;
        }

        protected override void UpdateSampleInsertWhiteReference()
        {
            if (this.sample_insert_white_reference != null)
            {
                Spectrum spectrum = this.sample_insert_white_reference.Clone();
                this.SetReferenceRawspectrumData(spectrum);
                spectrum.ApplyCorrectionsToRawData(this.CorrectionMask & ~CorrectionMask.DarkIntensity);

                this.processing_sample_insert_white = spectrum;
            }
            else
                this.processing_sample_insert_white = null;
        }

        protected override void UpdateTransflactenceInsertReference()
        {
            if (this.transflectance_insert_reference != null)
            {
                Spectrum spectrum = this.transflectance_insert_reference.Clone();
                this.SetSampleRawspectrumData(spectrum);
                spectrum.ApplyCorrectionsToRawData(this.CorrectionMask & ~CorrectionMask.DarkIntensity);

                this.processing_transflectance_insert = spectrum;
            }
            else
                this.processing_transflectance_insert = null;
        }

        protected override void UpdateWhiteReference()
        {
            if (this.white_reference != null)
            {
                Spectrum spectrum = this.white_reference.Clone();
                this.SetReferenceRawspectrumData(spectrum);
                spectrum.ApplyCorrectionsToRawData(this.CorrectionMask & ~CorrectionMask.DarkIntensity);

                this.processing_white = spectrum;
            }
            else
                this.processing_white = null;
        }

        protected override void UpdateOxidOfReference()
        {
            if (this.fix_two_glass_oxide != null && this.black_reference != null && this.white_reference != null)
            {
                Spectrum spectrum = this.fix_two_glass_oxide.Clone();
                spectrum.Reference = this.white_reference.Clone();
                spectrum.Reference.RawIntensity -= this.black_reference.RawIntensity;
                spectrum.RawIntensity -= this.black_reference.RawIntensity;
                spectrum.DarkIntensity = new DarkIntensity(double.Epsilon, spectrum.DarkIntensity.Sigma);
                spectrum.WavelengthLimits = this.fix_two_glass_oxide.WavelengthLimits;

                byte wlc_id;
                WavelengthCorrection wc = this.CalculateWavelengthCorrection(spectrum, true, out wlc_id);
                spectrum.WavelengthCorrection = wc;
                spectrum.WlcMasterSpectrumId = wlc_id;
                this.wavelength_correction_of_references = new WavelengthCorrection(wc);
                this.wavelength_correction_of_sample = new WavelengthCorrection(wc);
                this.corrected_oxide_of_reference = spectrum;
                this.corrected_oxide_of_sample = spectrum;
                this.sample_wavelength_correction_id = wlc_id;
                this.reference_wavelength_correction_id = wlc_id;
            }
        }

        protected override void UpdateOxidOfSample()
        {
            this.UpdateOxidOfReference();
        }
    }
}
