using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using iSTP_Embedded;

namespace iSTP_DataProcessing
{
    /// <summary>
    /// Provides data processing during pressure mode
    /// </summary>
    public class PressureMode
    {
        private List<PressureModeSensor> Elements;
        private int RefTempIndex;
        private double LastTime;

        private const string SENS_SPECIFIC = "mbar";
        private const double TimePeriod = 5d; //[s]

        public static float SetpointTemp;
        public static float SetpointStatic;
        public static float SetpointPitot;

        public PressureMode()
        { 
            
        }

        public void Configurate(string destination, ISTPConfiguration embConfig)
        {
            foreach(ISTPConfiguration.Sensor_t sensor in embConfig.Sensors)
            {
                if(sensor.Quantities.Contains(SENS_SPECIFIC))
                {
                    Elements.Add(new PressureModeSensor());
                    Elements[Elements.Count - 1].Create(destination, sensor);
                }
            }
        }

        public void AddNewData(EmbeddedPacket packet)
        {
            foreach (PressureModeSensor Dr_elementinos in Elements)
            {
                Dr_elementinos.Add(
                    SetpointTemp,
                    SetpointStatic,
                    SetpointPitot,
                    packet[RefTempIndex],
                    packet[Dr_elementinos.GetStaticIndex],
                    packet[Dr_elementinos.GetPitotIndex],
                    packet[Dr_elementinos.GetTempStaticIndex],
                    packet[Dr_elementinos.GetTempPitotIndex]);
            }

            if ((packet.MsgTimeStamp - LastTime) > TimePeriod)
            {
                WriteData();
                LastTime = packet.MsgTimeStamp;
            }
        }

        private void WriteData()
        {
            foreach (PressureModeSensor Dr_elementinos in Elements)
            {
                Dr_elementinos.Write();   
            }
        }

        public void Close()
        {
            foreach (PressureModeSensor Dr_elementinos in Elements)
            {
                Dr_elementinos.Close();
            }
        }

        private class PressureModeSensor
        {
            #region --------------------------- Private global values ---------------------------
            private CSVwriter WFILE;
            private List<float[]> DATA;
            private int StaticIndex;
            private int PitotIndex;
            private int TempStaticIndex;
            private int TempPitotIndex;

            private string[] Headers = new string[] 
                {
                "Commanded temp (°C)",
                "Commanded static (mbar)",
                "Commanded pitot (mbar)",
                "Actual temp (°C)",
                "Static pressure (mbar)",
                "Pitot pressure (mbar)",
                "Static temp (°C)",
                "Pitot temp (°C)",
                "Not used",
                "Not used"
                };
            private string GetHeaders { get { return String.Join(",", Headers); } }

            #endregion

            #region --------------------------- Public global values ---------------------------
            #endregion

            #region --------------------------- Structures&Enums ---------------------------
            #endregion

            #region --------------------------- Construcotrs&Destructor ---------------------------
            public PressureModeSensor()
            {
                DATA = new List<float[]>();
            }
            #endregion

            #region --------------------------- Private sector ---------------------------
            private void Write(string line)
            {
                this.WFILE.WriteValue(line);
                this.WFILE.WriteNewLine();
                this.WFILE.BaseStream.Flush();
            }
            #endregion

            #region --------------------------- Protected sector ---------------------------
            #endregion

            #region --------------------------- Public sector ---------------------------
            public bool Create(string destination, ISTPConfiguration.Sensor_t sensor)
            {
                try
                {
                    if(sensor.QuantityIndexes.Length >= 2)
                    {
                        StaticIndex = sensor.QuantityIndexes[0];
                        PitotIndex = sensor.QuantityIndexes[1];
                    }

                    this.WFILE = new CSVwriter
                        (
                            new FileStream
                                (
                                    string.Format("{0}{1}{2}.csv", destination, Path.DirectorySeparatorChar, sensor.LongName),
                                    FileMode.Create,
                                    FileAccess.Write
                                )
                        );
                    Write(GetHeaders);
                    return true;
                }
                catch (Exception ex)
                {
                    iSTP_DebugConsole.DebugConsole.WriteLine(string.Format("Can't create file -> {0}", ex));
                    return false;
                }
            }

            public void Close()
            {
                try
                {
                    if (this.WFILE != null)
                    {
                        this.WFILE.BaseStream.Flush();
                        this.WFILE.BaseStream.Close();
                        this.WFILE = null;
                    }
                }
                catch (Exception ex)
                {
                    iSTP_DebugConsole.DebugConsole.WriteLine(string.Format("Can't close file -> {0}", ex));
                }
            }

            public bool Add(float SetTemp, float SetStatic, float SetPitot, float ActTemp, float ActStatic, float ActPitot, float ActTempStatic, float ActTempPitot)
            {
                try
                {
                    DATA.Add(new float[]
                    {
                        SetTemp,
                        SetStatic,
                        SetPitot,
                        ActTemp,
                        ActStatic,
                        ActPitot,
                        ActTempStatic,
                        ActTempPitot,
                        0f,
                        0f
                    });
                    return true;
                }
                catch (Exception ex)
                {
                    iSTP_DebugConsole.DebugConsole.WriteLine(string.Format("Error during saving data -> {0}", ex));
                    return false;
                }
            }

            public bool Write()
            {
                try
                {
                    float[] _arr = new float[DATA[0].Length];
                    foreach (float[] dataline in DATA)
                    {
                        for (int i = 0; i < _arr.Length; i++)
                        {
                            _arr[i] += dataline[i];
                        }
                    }

                    for (int i = 0; i < _arr.Length; i++)
                    {
                        _arr[i] = _arr[i] / DATA.Count;
                    }

                    _arr[_arr.Length - 1] = 0;
                    _arr[_arr.Length - 2] = 0;

                    string line = string.Empty;
                    for (uint i = 0; i < _arr.Length; i++)
                    {
                        if ((i + 1) != _arr.Length)
                            line += string.Format("{0},", _arr[i]);
                        else
                            line += string.Format("{0}", _arr[i]);
                    }

                    Write(line);
                    DATA.Clear();
                    return true;
                }
                catch (Exception ex)
                {
                    iSTP_DebugConsole.DebugConsole.WriteLine(string.Format("Can't write data in file -> {0}", ex));
                    return false;
                }
            }

            public int GetStaticIndex {get { return StaticIndex;}}
            public int GetPitotIndex {get {return PitotIndex;}}
            public int GetTempStaticIndex { get { return TempStaticIndex; } }
            public int GetTempPitotIndex { get { return TempPitotIndex; } }
            #endregion
        }
    }
}
