using System;
using System.Text;
using System.IO;
using iSTP_Embedded;

namespace iSTP_DataProcessing
{
    /// <summary>
    /// Controller for csv writer
    /// </summary>
    class CSVLogger
    {
        private CSVwriter[] MyCSVwriters;
        private ISTPConfiguration EmbConfiguration;
        private string DestinationDirectory;
        private bool PerSensorLogging;
        private string[] HeaderRows;
        private string[] LogNames;
        
        /// <summary>
        /// Sets up CSV files configuration based on user choice and current configuration
        /// </summary>
        /// <param name="destination"></param>
        /// <param name="embConfig"></param>
        /// <param name="perSensorLog"></param>
        public CSVLogger(string destination, ISTPConfiguration embConfig, bool perSensorLog)
        {
            DestinationDirectory = destination;
            
            if (!Directory.Exists(DestinationDirectory))
                Directory.CreateDirectory(DestinationDirectory);
            embConfig.DumpConfiguration(DestinationDirectory + "\\EmbeddedConfig.txt");
            
            EmbConfiguration = embConfig;
            PerSensorLogging = perSensorLog;

            if (PerSensorLogging)
            {
                MyCSVwriters = new CSVwriter[EmbConfiguration.Size];
                HeaderRows = new string[EmbConfiguration.Size];
                LogNames = new string[EmbConfiguration.Size];

                for (int i = 0; i < EmbConfiguration.Size; i++)
                {
                    LogNames[i] = EmbConfiguration[i].LongName;

                    HeaderRows[i] = "Packet #,Time[s]";

                    foreach (string quantity in EmbConfiguration[i].Quantities)
                    {
                        HeaderRows[i] = string.Format("{0},{1}", HeaderRows[i], String.Format("{0}_{1}", EmbConfiguration[i].LongName, quantity));
                    }
                }
            }
            else // all-in-one
            {
                HeaderRows = new string[1];
                HeaderRows[0] = "Packet #,Time[s]";

                for (int i = 0; i < embConfig.Size; i++)
                {
                    foreach (string quantity in embConfig.Sensors[i].Quantities)
                    {
                        HeaderRows[0] = string.Format("{0},{1}", HeaderRows[0], String.Format("{0}_{1}", embConfig.Sensors[i].LongName, quantity));
                    }
                }
            }
        }

        /// <summary>
        /// Creates data CSV files
        /// </summary>
        /// <param name="destination">Destination</param>
        public void LogStart(string destination)
        {
            string DestinationDirectory = destination;

            if (PerSensorLogging)
            {
                MyCSVwriters = new CSVwriter[EmbConfiguration.Size];

                for (int i = 0; i < EmbConfiguration.Size; i++)
                {
                    MyCSVwriters[i] = CreateNewLog(string.Format("{0}\\{1}.csv", DestinationDirectory, LogNames[i]), HeaderRows[i]);
                }
            }
            else // all-in-one
            {
                MyCSVwriters = new CSVwriter[1];
                MyCSVwriters[0] = CreateNewLog(DestinationDirectory + "\\All-in-one.csv", HeaderRows[0]);
            }
        }

        private Double[] fakeTime = new Double[1000];

        /// <summary>
        /// Saves one data packet
        /// </summary>
        /// <param name="packet"></param>
        public void LogData(EmbeddedPacket packet)
        {
            if (MyCSVwriters != null)
            {
                if (PerSensorLogging)
                {
                    for (int sensorIndex = 0; sensorIndex < EmbConfiguration.Size; sensorIndex++)
                    {
                        try
                        {
                            MyCSVwriters[sensorIndex].WriteValue(packet.MsgNumber.ToString());
                            MyCSVwriters[sensorIndex].WriteValue(packet.MsgTimeStamp.ToString());
                            foreach (int quantityIndex in EmbConfiguration[sensorIndex].QuantityIndexes)
                            {
                                MyCSVwriters[sensorIndex].WriteValue(packet[quantityIndex].ToString());

                            }
                            MyCSVwriters[sensorIndex].WriteNewLine();
                        }
                        catch (Exception e) 
                        {
                            DataProcessingError.Add("CSVLogger.cs", "Exception in log data controller", e.ToString());
                        }
                    }
                }
                else // all-in-one
                {
                    MyCSVwriters[0].WriteValue(packet.MsgNumber.ToString());
                    MyCSVwriters[0].WriteValue(packet.MsgTimeStamp.ToString());
                    for (int i = 0; i < (packet.MsgLength / sizeof(Single)); i++)
                    {
                        MyCSVwriters[0].WriteValue(packet.GetData(i).ToString());
                    }
                    MyCSVwriters[0].WriteNewLine();

                }
            }
        }

        /// <summary>
        /// Creates new log file with input string and write input headers in it
        /// </summary>
        /// <param name="fileName">File name</param>
        /// <param name="headerRow">Name of each column delimitier is ,</param>
        /// <returns></returns>
        private CSVwriter CreateNewLog(string fileName, string headerRow)
        {
            FileStream dataLogFile = new FileStream(fileName, FileMode.Create, FileAccess.Write);
            CSVwriter writer = new CSVwriter(dataLogFile);
            writer.BaseStream.Write(Encoding.ASCII.GetBytes(headerRow), 0, headerRow.Length);           
            writer.WriteNewLine();
            return (writer);
        }

        /// <summary>
        /// Close all opened files and free memory
        /// </summary>
        public void Terminate()
        {
            
            if (MyCSVwriters != null)
            {
                for (int i = 0; i < MyCSVwriters.Length; i++ )
                {
                    if(MyCSVwriters[i] != null)
                    {
                        MyCSVwriters[i].BaseStream.Close();
                        MyCSVwriters[i].BaseStream = null;
                        MyCSVwriters[i] = null;
                    }
                }
                MyCSVwriters = null;
            }
        }

    }
}
