
//
//  SampleIdWindow.cs
//
// QuickStep: Acquire, view and identify spectra 
// Copyright (C) 2010-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.IO;
using Hiperscan.Unix;

namespace Hiperscan.Extensions.Acquisition
{
    public partial class TestProcess
    {
        public TestProcess()
        {
            this.OutPath = Path.GetTempPath();
            this.OutPath = Path.Combine(this.OutPath, Guid.NewGuid().ToString());
        }

        public void ProcessSpectra()
        {
            if (TestProcess.IsAvailable == false)
                return;

            try
            {
                TestProcess.Started?.Invoke(this, EventArgs.Empty);

                FileIO.RecreateDirectory(this.OutPath);

                this.CorrectionSucceded = false;
                this.NumberOfProcessed = 0;

                this.ExecuteCorrectionTool();

                if (this.CorrectionSucceded)
                    TestProcess.Succeded?.Invoke(this, EventArgs.Empty);
                else
                    TestProcess.Failed?.Invoke(this, EventArgs.Empty);
            }
            catch (Exception ex)
            {
                this.LastException = ex;
                TestProcess.ExecutionFailed?.Invoke(this, EventArgs.Empty);
            }
            finally
            {
                try { FileIO.DeleteDirectory(this.OutPath, true); } catch (Exception) { }
            }
        }

        private void ExecuteCorrectionTool()
        {
            string output = String.Empty;

            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo.FileName = TestProcess.MonoPath;
            process.StartInfo.Arguments = this.GenerateArgs();
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.StandardOutputEncoding = TestProcess.Encoding;
            process.StartInfo.WorkingDirectory = Path.GetDirectoryName(TestProcess.CorrectiontoolExe);
            process.OutputDataReceived += (sender, e) => output += e.Data;

            process.Start();
            process.BeginOutputReadLine();
            process.WaitForExit();

            if (process.ExitCode != 0)
            {
                string message = String.Format(Catalog.GetString("CorrectionTool process finished with exit code: {0}"),
                                               process.ExitCode);
                throw new Exception(message);
            }

            this.CheckCorrectionsSuccess(output);
        }


        private string GenerateArgs()
        {
            string sample_regex = String.Format(@"^{0}_\d+\.csv$", this.SequenceNumber);
            int threads = Environment.ProcessorCount;
            if (threads < 1)
                threads = 1;

            string args = String.Format("\"{0}\" ", TestProcess.CorrectiontoolExe);
            args += "--no-adc-correction ";
            args += String.Format("--sample-regex \"{0}\" ", sample_regex);
            args += String.Format(" --thread-count {0} ", threads);

            if (this.IsFluid)
            {
                args += "--process-mode Fluid ";
            }
            else if (this.IsInsert)
            {
                args += "--process-mode Insert  --correlation-threshold 0.9 ";
                args += "";
            }
            else
            {
                args += "--process-mode Solid  --variance-check --no-zero-absorbance-check ";
            }

            args += String.Format("--output-dir \"{0}\" ", this.OutPath);
            args += String.Format("\"{0}\"", this.RawDateDir);


            Console.WriteLine("TestProcessing - args = {0}", args);

            return args;
        }

        private void CheckCorrectionsSuccess(string output)
        {
            string match = TestProcess.EvaluationRegex.Match(output).Value;
            if (String.IsNullOrEmpty(match))
                return;

            string number = match.Split(new char[] { ' ' })[0];
            this.NumberOfProcessed = Int32.Parse(number);

            this.CorrectionSucceded = this.NumberOfAcquisitions == this.NumberOfProcessed;
        }

        private string sequence_number = String.Empty;
        public string SequenceNumber 
        {
            get
            {
                return this.sequence_number;
            }

            set
            {
                this.sequence_number = value;
                if (this.IsInsert == false)
                    this.sequence_number = this.sequence_number.Replace("SI", String.Empty);
            }
        }

        public bool IsInsert { get; set; }
        public bool IsFluid { get; set; }
        public int NumberOfAcquisitions { get; set; } = -1;
        public string RawDateDir { get; set; }
        private string OutPath { get; set; }

        public Exception LastException { get; private set; }
        private bool CorrectionSucceded { get; set; }
        public int NumberOfProcessed { get; private set; }
    }
}
