// Created with MonoDevelop
//
//    Copyright (C) 2019 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.Collections.Generic;

using Hiperscan.SGS.Benchtop;
using Hiperscan.SGS.Benchtop.FinderSetup;
using Hiperscan.SGS.Benchtop.LightSourceControl;
using Hiperscan.SGS.Common;
using Hiperscan.SGS.SerialInterface;
using Hiperscan.Spectroscopy;
using Hiperscan.SGS.Benchtop.TemperatureControl;
using Hiperscan.SGS.Benchtop.TouchBoard;
using static Hiperscan.SGS.SgsNt.Protocol.BaseProtocol;

namespace Hiperscan.SGS
{
    public delegate void NewExceptionHandler(SgsException ex);
    public delegate void NewWarnigHandler(IDevice dev, string msg);
    public delegate void BeforeDisconnectHandler(IDevice device);
    public delegate void RemovedHandler(IDevice device);
    public delegate void StateChangedHandler(IDevice device);
    public delegate void NewSingleHandler(IDevice device, Spectrum spectrum);
    public delegate void NewStreamHandler(IDevice device, Spectrum spectrum);
    public delegate void NewQuickStreamHandler(IDevice device, Spectrum spectrum);

    public interface IDevice
    {
        event NewExceptionHandler NewException;
        event NewWarnigHandler NewWarning;
        event BeforeDisconnectHandler BeforeDisconnect;
        event RemovedHandler Removed;
        event StateChangedHandler StateChanged;
        event NewSingleHandler NewSingle;
        event NewStreamHandler NewStream;
        event NewQuickStreamHandler NewQuickStream;
        event IdleTaskHandler IdleTask;

        //Position control
        int FinderPosition { get; }
        string FinderPositionName { get; }
        string FinderPositionTypeName { get; }
        FinderPositionType FinderPositionType { get; }
        void SetFinderPosition(int position, IdleTaskHandler idle_task, bool no_wait = false);


        //light source control
        bool FinderLightSourceState { get; }
        void SetFinderLightSource(bool on, IdleTaskHandler idle_task);
        void ResetLightSourceStats();
        short LightSourceReady();
        uint LightSourceDelay { get; set; }
        void SetLightSourceConfig(LightSourceConfig config);
        LightSourceQuery CurrentLightSourceState { get; }
        void ReadLightSourceState();
        LightSourceOperatingTimes LightSourceOperatingTimes { get; }
        void ReadLightSourceVoltages();
        LightSourceSettings LightSourceSettings { get; }
        void ReadLightSourceOperatingTimes();
        void ResetLightSourceOperatingTimes();
        void WriteLightSourceVoltages(LightSourceSettings light_voltages);
        TouchBoardLEDs TouchBoardLEDs { get; set; }
        byte ReadTouchButtonLightState();

        //temperature
        void WriteTemperatureControlInput(byte[] key, byte val); //not used for NT
        byte ReadTemperatureControlInput(); //not used for NT
        //HW command 
        void WriteTemperatureControlInfo(byte[] key, byte version, byte control_value, double target_temperature);
        //HR command
        void ReadTemperatureControlInfo(out byte version, out byte control_value, out double target_temperature);
        //FT command
        double ReadFinderTemperature();
        //NT: read pver readspectrum and readstate
        double LastTemperature { get; }
        TemperatureHistory TemperatureHistory { get; } //not used for NT

        //new version: TODO refactoring with all older methods above
        DeviceTemperatures Temperatures { get; }
        void WriteTemperatures(bool set_pid = false);
        void ReadTemperatures();
        void ResetTemperatures();
        void SetCapsuleTemperature();
        void SetDetectorTemperature(bool set_pid);
        void WriteSamplePositionDetection(SamplePositionDetectionData sample_positions);


        bool IsConnected { get; }
        bool IsIdle { get; }
        bool IsUnknown { get; }
        bool StateNotification { get; set; }
        Spectrometer.Config CurrentConfig { get; set; }
        bool ConfigHasChanged { get; }
        bool HasReference { get; }
        DataSet Frequency { get; }
        AcquisitionInfo AcquisitionInfo { get; }
        CalibrationInfo CalibrationInfo { get; set; }
        bool AutoRecalibrationIsPending { get; }
        SpectrumQueue SpectrumQueue { get; }
        DeviceInfo Info { get; }
        ulong SpectrumCount { get; set; }
        bool IsUnprogrammed { get; }
        bool IsFinder { get; }
        bool CanAcquireSpectra { get; }
        bool AssumedFinderLEDState { get; }
        bool LimitBandwith { get; set; }
        DriverType DriverType { get; }
        VersionInfo VersionInfo { get; }
        Common.Version ProtocolVersion { get; }
        Common.Version ScanEngineVersion { get; }
        Common.Version HardwareVersion { get; }
        string FirmwareVersion { get; }
        string FirmwareRevision { get; }
        DateTime LutTimestamp { get; }
        bool IsShared { get; }
        FinderVersion FinderVersion { get; }
        SpectrometerVersion SpectrometerVersion { get; }
        bool HasKeyPad { get; }
        HardwareProperties HardwareProperties { get; }

       

        bool DisableInternalExceptionHandling { get; set; }
        int MinAverage { get; }
        bool IgnoreSgsExceptions { get; set; }
        int MaxAverage { get; }
        int LutLength { get; }


        void Open(bool auto_init = true);
        void Close();
        void WriteEEPROM();
        void StartSingle(bool auto_finder_light);
        Spectrum Single(bool auto_finder_light, IdleTaskHandler idle_task);
        IEnumerable<Spectrum> MultiSample(Dictionary<int, string> motor_positions);
        IEnumerable<Spectrum> MultiSample(Dictionary<int, string> motor_positions, bool auto_finder_light);
        IEnumerable<Spectrum> MultiSample(Dictionary<int, string> motor_positions, IdleTaskHandler idle_task);
        IEnumerable<Spectrum> MultiSample(Dictionary<int, string> motor_positions,bool auto_finder_light, IdleTaskHandler idle_task);
        Spectrum SingleLineScan(ushort average = 3000, Spectrometer.TriggerType trigger_type = Spectrometer.TriggerType.TripletScanCustom, bool auto_finder_light = false, IdleTaskHandler idle_task = null);
        void ReadFinderDataExtended();
        void StartBootLoaderMode();

        void StartQuickStream();
        void StartStream();
        void StopStream();
        void StartSingle();
        Spectrum Single();
        Spectrum Single(bool auto_finder_light);
        Spectrum Single(IdleTaskHandler idle_task);
        void WriteConfig();
        int GetKeyPadSize();
        bool FinderButtonPressed();
        void SwitchFinderStatusLED(bool green);
        void SwitchFinderStatusLED(bool hw_linked, bool blinking);

        void SetFinderFanSpeed(bool on);
        void SetMaintenanceMode(byte[] key);
        void SetExtendedSpectrumMode(byte[] key);
        void SetOscillationMode(byte[] key, ushort factor);
        void SetTestMode(byte[] key, byte mode, ushort param);
        void WriteSerialNumber(byte[] key, string serial);
        string ReadSerialNumber();
        void WriteOemSerialNumber(string serial);
        string ReadOemSerialNumber();
        string ReadSystemLog(byte[] key);
        void WriteUsbProductId(byte[] key, UInt16 pid);
        void WriteLut(byte[] key, Spectrometer.LUT lut);
        void WriteMasterKey(byte[] maintenance_key, byte[] key);
        byte[] ReadMasterKey(byte[] challenge);
        void WriteIndividualKey(byte[] maintenance_key, byte[] key);
        byte[] ReadIndividualKey(byte[] challenge);
        void WriteAverageCount(ushort count);
        ushort ReadAverageCount();
        void WriteAdcResolution(byte[] key, byte bits);
        byte ReadAdcResolution();
        void WriteSampleCount(ushort count);
        ushort ReadSampleCount();
        uint ReadClockFrequency();
        void WriteStepperMotorParameters(byte[] key, byte[] parameters);
        byte[] ReadStepperMotorParameters();
        void WriteDimmerParameter(byte[] key, byte val);
        byte ReadDimmerParameter();
        int ReadAcquisitionOffset();


        void WriteEEPROM(byte addr, Int32 val);
        Int32 ReadEEPROM(byte addr);
        double ReadStatus();
        SystemStats ReadSystemStats();

        void ResetSystemOperatingHours(byte[] key);
        void SetFinderStatus(FinderStatusType status);

        bool FinderOnInitPosition();
        void SetAdcCount(byte[] key, ushort samples);
        ushort[] ReadAdcValues(byte[] key);
        void WriteAdcCorrection(byte[] key, double[] parameters);
        void WriteFinderPcbHardwareVersion(byte[] key, byte[] versions);
        void WriteFinderOverrideHardwareVersion(byte[] key, byte[] versions);
        byte[] ReadFinderHardwareVersion();
        void WriteFinderPCBCommand(byte[] command);
        DataSet ReadAdcCorrection();
        void WriteHardwareVersion(byte[] key, byte major, byte minor);
        void WriteHardwareProperties(byte[] key, HardwareProperties device_properties);
        Spectrum AcquireAdcBufferSpectrum(byte[] key, UInt16[] buf);

        void WriteFinderIdleTime(uint idle_seconds);
        uint ReadFinderIdleTime();
        void WriteSessionTimeout(ushort timeout_seconds);
        void StartSampleSpinner(sbyte velocity);
        void StopSampleSpinner();
        void RotateSampleSpinner(sbyte velocity, ushort angle);
        void WriteSampleSpinnerCorrections(double slope, double offset);
        void ReadSampleSpinnerCorrections(out double slope, out double offset);
        void WriteScanEngineMsaFactor(byte[] key, double msa_factor);
        void ResetSampleSpinnerCounter();
        double ReadScanEngineMsaFactor();
        uint ReadSampleSpinnerCounter();
        void WaitForIdle(int timeout);
        Spectrometer.State GetState();
        void SetAbsorbance(Spectrum spectrum);
        void SetWavelengthCorrection(Spectrum spectrum);
        void Share(uint port);
        void Unshare();
        ProbeType GetFinderProbeType();
        bool SetState(Spectrometer.State state);
        void RemoveNotify();
        void RebootToBootloader();
        void SetParkState(bool lock_spectrometer);
        bool ReadParkStateIsLocked();
        void StartTestMode(byte test_mode);
        PositionDetectionSensorReadData ReadSamplePositionDetectionSensors();
        SamplePositionDetectionData ReadSamplePositionDetection();
        string ReadLastSystemLogEntry();
        string ReadVersionString();
        uint ReadCpuFrequency();


        //UNDO
        ISerialInterface Interface { get; }
    }
}