// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2018 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;


namespace Hiperscan.Extensions.ApoIdentCommon
{
    public enum ScannerInfoType
    {
        Complete,     // Substance ID / Name available, additional information is optional
        Incomplete,   // no Substance ID / Name available
        Invalid       // GUI shows Info dialoge "Invalid Scanner data."
    }

    public class ScannerInfo
    {
        // mandatory information (set in ctor)
        public ScannerInfoType InfoType { get; private set; }
        public string SubstanceName     { get; private set; }
        public string SubstanceId       { get; private set; }

        // optional informatio leave null if not available
        public string SupplierName        { get; private set; }
        public string BatchNumber         { get; private set; }
        public string WeightingCorrection { get; private set; }
        public string PZN                 { get; private set; }
        public DateTime? ExpirationDate   { get; private set; }

        public string FullCode              { get; private set; } = String.Empty;
        public DateTime AcquisitionTStamp   { get; private set; }  = DateTime.Now;
        public string DataCode              { get; private set; }  = String.Empty;


        public ScannerInfo(ScannerInfoType info_type, string substance_name = null, string substance_id = null)
        {
            if (info_type == ScannerInfoType.Complete)
            {
                if (string.IsNullOrEmpty(substance_name))
                    throw new ArgumentException("No Substance Name defined.");

                if (string.IsNullOrEmpty(substance_id))
                    throw new ArgumentException("No Substance ID defined.");
            }

            this.InfoType = info_type;
            this.SubstanceName = substance_name;
            this.SubstanceId = substance_id;
        }

        public void SetSupplierName(string supplier_name)
        {
            this.SupplierName = supplier_name;
        }

        public void SetBatchNumber(string batch_number)
        {
            this.BatchNumber = batch_number;
        }

        public void SetWeightingCorrection(string weighting_correction)
        {
            this.WeightingCorrection = weighting_correction;
        }

        public void SetPZN(string pzn)
        {
            this.PZN = pzn;
        }

        public void SetExpirationDate(DateTime expiration_date)
        {
            if (expiration_date < new DateTime(2000, 1, 1))
                this.ExpirationDate = null;
            else
                this.ExpirationDate = expiration_date;
        }

        public override string ToString()
        {
            return string.Format("[ScannerInfo: InfoType={0}, SubstanceName={1}, SubstanceId={2}, SupplierName={3}, BatchNumber={4}, WeightingCorrection={5}, PZN={6}, ExpirationDate={7}]", InfoType, SubstanceName, SubstanceId, SupplierName, BatchNumber, WeightingCorrection, PZN, ExpirationDate);
        }

        public string _WriteToSummarize()
        {

            SeparatedParams asp = new SeparatedParams("");

            asp.SetParamByID("ScannerInfo", "OK");
            asp.SetParamByID("InfoType", InfoType.ToString());
            asp.SetParamByID("PZN", PZN);
            asp.SetParamByID("SubstanceName", SubstanceName);
            asp.SetParamByID("SubstanceID", SubstanceId);
            asp.SetParamByID("SupplierName", SupplierName);
            asp.SetParamByID("BatchNumber", BatchNumber);
            asp.SetParamByID("ExpirationDate", ExpirationDate.ToString());
            asp.SetParamByID("FullCode", FullCode);
            asp.SetParamByID("AcqTimeStamp", AcquisitionTStamp.ToString());
            asp.SetParamByID("DataCode", DataCode);
            asp.SetParamByID("WeightingCorrection", WeightingCorrection);

            string ss = asp.SumString(';');

            asp = null;
            return ss;
        }

        public bool _ReadFromSummarize(string avalue)
        {

            string ss = "";
            DateTime dt;
            if (avalue.Length < 1)
                return false;
            SeparatedParams asp = new SeparatedParams(avalue);
            try
            {
                ss = asp.GetParamByID("ScannerInfo");
                if (!ss.Equals("OK"))
                    return false;

                ss = asp.GetParamByID("InfoType");
                if (ss.Equals("Invalid")) InfoType = ScannerInfoType.Invalid;
                if (ss.Equals("Incomplete")) InfoType = ScannerInfoType.Incomplete;
                if (ss.Equals("Complete")) InfoType = ScannerInfoType.Complete;

                ss = asp.GetParamByID("PZN");
                SetPZN(ss);

                ss = asp.GetParamByID("SubstanceName");
                SubstanceName = ss;

                ss = asp.GetParamByID("SubstanceID");
                SubstanceId = ss;

                ss = asp.GetParamByID("SupplierName");
                SetSupplierName(ss);

                ss = asp.GetParamByID("BatchNumber");
                SetBatchNumber(ss);

                ss = asp.GetParamByID("ExpirationDate");
                try
                {
                    dt = DateTime.Parse(ss);
                }
                catch (Exception ex)
                {
                    dt = new DateTime(1902, 1, 1, 0, 0, 0);
                }
                SetExpirationDate(dt);

                ss = asp.GetParamByID("FullCode");
                FullCode = ss;

                ss = asp.GetParamByID("AcqTimeStamp");
                try
                {
                    dt = DateTime.Parse(ss);
                }
                catch (Exception ex)
                {
                    dt = new DateTime(1901, 1, 1, 0, 0, 0);
                }
                AcquisitionTStamp = dt;

                ss = asp.GetParamByID("DataCode");
                DataCode = ss;

                ss = asp.GetParamByID("WeightingCorrection");
                WeightingCorrection = ss;

                return true;
            }
            finally
            {
                asp = null;
            }

        }
    }

    public interface IScanner
    {
        // version number of the Scanner Software module
        Version Version { get; }

        // type (designation) of the Scanner device, null if not available
        string ScannerType { get; }

        // initialize Scanner Software module (executed if module is available while Apo-Ident Init())
        int Init();

        // deinit Scanner Software module (executed if module is available while Apo-Ident Quit())
        int Exit();

        // read Scanner information from Software module, return information aqcuired while last scan or null if no data is available
        // if an information has been returned, next call must result in null
        ScannerInfo GetScannerInfo();
    }
}