using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using iSTP_DebugConsole;

namespace ClimaChamber
{
    /// <summary>
    /// Interface for climatic chamber driver
    /// </summary>
    interface IClimaticChamber
    {
        /// <summary>
        /// Try to connect to climatic chamber by serial port
        /// </summary>
        /// <param name="portName">COM name</param>
        /// <param name="baudRate">Communication speed</param>
        /// <param name="dataBits">Data length in comunication</param>
        /// <param name="stopBits">Number of stop bits</param>
        /// <param name="parity">Type of parity</param>
        /// <returns>TRUE - connection is open</returns>
        bool Connect(string portName,
                     string baudRate,
                     string dataBits,
                     string stopBits,
                     string parity);
        /// <summary>
        /// Try to connect to climatic chamber by ethernet
        /// </summary>
        /// <param name="iIP">destination IP</param>
        /// <param name="port">destination port</param>
        /// <returns>TRUE - connection is open</returns>
        bool Connect(IPAddress iIP, int port);
        /// <summary>
        /// Disconnected from device
        /// </summary>
        void Disconnect();
        /// <summary>
        /// Try to set temperature set-point in climnatic chamber
        /// </summary>
        /// <param name="iTemp">Temperature set-point [Celsius]</param>
        /// <returns>TRUE - success</returns>
        bool SetTemperature(float iTemp);
        /// <summary>
        /// Try to set humidity set-point in climatic chamber
        /// </summary>
        /// <param name="iHumi">Humidity set-point [%]</param>
        /// <returns>TRUE - success</returns>
        bool SetHumidity(float iHumi);
        /// <summary>
        /// Try to set temeprature and humidity set-points
        /// </summary>
        /// <param name="iTemp">Temperature set-point [Celsius]</param>
        /// <param name="iHumi">Humidity set-point [%]</param>
        /// <returns>TRUE - success</returns>
        bool SetTempHumi(float iTemp, float iHumi);
        /// <summary>
        /// Gets actual temperature from device
        /// </summary>
        /// <returns>Actual temperature</returns>
        float GetActTemp();
        /// <summary>
        /// Gets actual humidity from device
        /// </summary>
        /// <returns>Actual humidity</returns>
        float GetActHumi();
        /// <summary>
        /// Gets actual nominal temperature from device
        /// </summary>
        /// <returns>Nominal temperature</returns>
        float GetNominalTemp();
        /// <summary>
        /// Gets nominal humidity from device
        /// </summary>
        /// <returns>Nominal humidity</returns>
        float GetNominalHumi();
        /// <summary>
        /// Checks error state and try to clear it
        /// </summary>
        /// <returns>TRUE - success, no error, error clear successfully</returns>
        bool CheckAndClearErr();
        /// <summary>
        /// Turn on device
        /// </summary>
        /// <returns>TRUE - success </returns>
        bool Run();
        /// <summary>
        /// Turn off device
        /// </summary>
        /// <returns>TRUE - success</returns>
        bool Stop();
        /// <summary>
        /// Set all possible gradients 
        /// </summary>
        /// <param name="iHeatGradient">Heating gradient</param>
        /// <param name="iCoolGradient">Coolng gradient</param>
        /// <param name="iHumidityGradient">Humidity gradient</param>
        /// <param name="iDeHumidityGradient">Dehumidity gradient</param>
        /// <returns>TRUE - success</returns>
        bool SetChangeRates(float iHeatGradient, float iCoolGradient, float iHumidityGradient, float iDeHumidityGradient);
        /// <summary>
        /// Set gradients for temperature (Heating=Cooling) and humidity (Humidity=Dehumidity)
        /// </summary>
        /// <param name="iHeatGradient">Heating(Cooling) gradient</param>
        /// <param name="iHumidityGradient">Humidity(Dehumidity) gradient</param>
        /// <returns></returns>
        bool SetChangeRates(float iHeatGradient, float iHumidityGradient);
        /// <summary>
        /// Gets time from last update
        /// </summary>
        /// <returns>Time and date from last update values</returns>
        DateTime LastUpdate();
        /// <summary>
        /// Set on driver automatic update
        /// </summary>
        /// <param name="iSleepInt">Frequency of updater</param>
        /// <returns>TRUE - success</returns>
        bool UpdaterStart(TimeSpan iSleepInt);
        /// <summary>
        /// Stop driver automatic update
        /// </summary>
        void UpdaterStop();
        /// <summary>
        /// Provides update of all values from device
        /// </summary>
        void ManualUpdate();
        /// <summary>
        /// Gets device name
        /// </summary>
        string ChamberName { get; }
        /// <summary>
        /// Set all possible parameters on device
        /// </summary>
        /// <param name="iHeatGradient">Heating gradient [Celsius/min]</param>
        /// <param name="iCoolGradient">Cooling gradient [Celsius/min]</param>
        /// <param name="iHumidityGradient">Humidity gradient [%/min]</param>
        /// <param name="iDeHumidityGradient">Dehumidity gradient [%/min]</param>
        /// <param name="iTemp">Nominal temperature [Celsius]</param>
        /// <param name="iHumi">Nominal humidity [%]</param>
        /// <returns>TRUE - success</returns>
        bool SetAll(float iHeatGradient, float iCoolGradient, float iHumidityGradient, float iDeHumidityGradient, float iTemp, float iHumi);
    }

    /// <summary>
    /// This class provides all errors which may appers in using diver.
    /// </summary>
    public static class ClimError
    {
        /// <summary>
        /// Type of error
        /// </summary>
        private static State_e State;
        /// <summary>
        /// This text will copy in debugg window for expert and contains all possible information about error.
        /// </summary>
        private static List<string> Fulltext = new List<string>();
        /// <summary>
        /// This text will copy in logger window for user information
        /// </summary>
        private static List<string> ShortText = new List<string>();
        /// <summary>
        /// Sources of error, function or class or both
        /// </summary>
        private static List<string> Source = new List<string>();
        /// <summary>
        /// All possible error state
        /// </summary>
        public enum State_e
        {
            /// <summary>
            /// Just information, Warning
            /// </summary>
            Normal,
            /// <summary>
            /// Stop running program
            /// </summary>
            Critical
        }

        /// <summary>
        /// TRUE - errors in memory, wating to be read by task
        /// </summary>
        public static bool isActive { get; private set; }

        /// <summary>
        /// Adds new error in memory
        /// </summary>
        /// <param name="source">Source of error, method or class or both</param>
        /// <param name="shortText">This text is information for User</param>
        /// <param name="fullText">This test is infomration for Expert</param>
        /// <param name="iscritical">TRUE - critical error set and program will stop</param>
        public static void Add(string source, string shortText, string fullText, bool iscritical = false)
        {
            isActive = true;
            Fulltext.Add(fullText);
            ShortText.Add(shortText);
            Source.Add(source);

            if (iscritical)
                State = State_e.Critical;
            else if (!iscritical && State != State_e.Critical)
                State = State_e.Normal;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="errors"></param>
        /// <returns></returns>
        public static State_e GetMsg(out List<string[]> errors)
        {
            isActive = false;
            errors = new List<string[]>();
            for (int i = 0; i < Fulltext.Count; i++)
                errors.Add(new string[]
                {
                    string.Format("Climatic chamber controller: Source[{0}] -> ShortText = {1}", Source[i], ShortText[i]),
                    string.Format("Climatic chamber controller: Source[{0}] -> ShortText = {1} -> FullText = {2}", Source[i], ShortText[i], Fulltext[i])
                });

            Source.Clear();
            ShortText.Clear();
            Fulltext.Clear();

            return State;
        }
    }
}
