using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using iSTP_Embedded;

namespace iSTP_DataProcessing
{
    /// <summary>
    /// Controller for HX files
    /// </summary>
    class HoneyxLogger
    {
        private HoneyxWriter[] MyHxWriters;
        private ISTPConfiguration EmbConfiguration;
        private string DestinationDirectory;
        private bool PerSensorLogging;
        private string InfoBlock;
        private string[] AllQuantities;
        private string[] LogNames;

        /// <summary>
        /// Initialize components according to current configuration and user choice
        /// </summary>
        /// <param name="destination">Root destination</param>
        /// <param name="embConfig">Current configuration</param>
        /// <param name="perSensorLog">All in one file or each sensor in own file</param>
        public HoneyxLogger(string destination, ISTPConfiguration embConfig, bool perSensorLog)
        {
            PerSensorLogging = perSensorLog;
            DestinationDirectory = destination;
            
            if (!Directory.Exists(DestinationDirectory))
                Directory.CreateDirectory(DestinationDirectory);
            embConfig.DumpConfiguration(DestinationDirectory + "\\EmbeddedConfig.txt");

            EmbConfiguration = embConfig;
            PerSensorLogging = perSensorLog;

            InfoBlock = CreateInfoBlock();

            if (PerSensorLogging)
            {
                MyHxWriters = new HoneyxWriter[EmbConfiguration.Size];
                LogNames = new string[EmbConfiguration.Size];

                for (int i = 0; i < EmbConfiguration.Size; i++)
                {
                    LogNames[i] = EmbConfiguration[i].LongName;
                }
            }
            else // all-in-one
            {
                List<string> quantityList = new List<string>();

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

        /// <summary>
        /// Sets up files into destination
        /// </summary>
        /// <param name="destination">Destination path</param>
        public void LogStart(string destination)
        {
            string DestinationDirectory = destination;
            
            if (PerSensorLogging)
            {
                MyHxWriters = new HoneyxWriter[EmbConfiguration.Size];

                for (int i = 0; i < EmbConfiguration.Size; i++)
                {
                    if (LogNames[i].Contains('\0'))
                    {
                        LogNames[i] = LogNames[i].Split('\0')[1];
                    }
                    MyHxWriters[i] = CreateNewLog(string.Format("{0}\\{1}.hx", DestinationDirectory, LogNames[i]), EmbConfiguration[i].Quantities);
                }
            }
            else // all-in-one
            {
                MyHxWriters = new HoneyxWriter[1];
                MyHxWriters[0] = CreateNewLog(string.Format("{0}\\All_in_one.hx",DestinationDirectory), AllQuantities);
            }
        }

        /// <summary>
        /// Create one file according to filename and his values.
        /// </summary>
        /// <param name="fileName">Name of file, sensor ID</param>
        /// <param name="quantities">Name of values from sensor</param>
        /// <returns>Created file</returns>
        private HoneyxWriter CreateNewLog(string fileName, string[] quantities)
        {
            HoneyxWriter HxWriter= new HoneyxWriter(fileName); 
            HxWriter.CreateFileWithLabels(HoneyxWriter.HoneyXIO_doubleTimeSingleData, 1, quantities.Length, String.Join(" ", quantities));
            InfoBlock = "AllInfoInEmbeddedConfigFile";
            HxWriter.WriteConfigurationText(InfoBlock);
            return HxWriter;
        }
        
        /// <summary>
        /// Create information block from current configuration
        /// </summary>
        /// <returns>All configuration in one string</returns>
        private string CreateInfoBlock()
        {
            string blockText = "";
            for (int i = 0; i < EmbConfiguration.Size; i++)
            {
                blockText += string.Format("{0}>>{1}\n@", EmbConfiguration[i].SensorName, EmbConfiguration[i].Comment);
                foreach (string quantity in EmbConfiguration[i].Quantities)
                {
                    blockText += String.Format("{0}_{1}@",
                                EmbConfiguration[i].LongName,
                                quantity);
                    if (EmbConfiguration[i].ConfigurationStatus.Parameters != null)
                    {
                        foreach (ISTPConfiguration.Parameter_t confParam in EmbConfiguration[i].ConfigurationStatus.Parameters)
                        {
                            blockText += String.Format("_{0}_{1}@", confParam.Name, confParam.CurrentOption);
                        }
                    }
                }
                blockText += "@@";
            }
            blockText = blockText.Replace(' ', '0');
            return blockText;
        }

        /// <summary>
        /// Saves data from packet
        /// </summary>
        /// <param name="packet">Current data packet</param>
        public void LogData(EmbeddedPacket packet)
        {
            try
            {
                if (MyHxWriters != null)
                {
                    if (PerSensorLogging)
                    {
                        for (int sensorIndex = 0; sensorIndex < EmbConfiguration.Size; sensorIndex++)
                        {
                            Single[] data = new Single[EmbConfiguration[sensorIndex].Quantities.Length];
                            int i = 0;
                            foreach (int quantityIndex in EmbConfiguration[sensorIndex].QuantityIndexes)
                            {
                                data[i++] = packet[quantityIndex];
                            }
                            if (MyHxWriters[sensorIndex] == null)
                                continue;
                            MyHxWriters[sensorIndex].WriteLine(packet.MsgTimeStamp, data);
                        }
                    }
                    else // all-in-one
                    {
                        Single[] data = new Single[packet.MsgLength / sizeof(Single)];
                        for (int i = 0; i < (packet.MsgLength / sizeof(Single)); i++)
                        {
                            data[i] = packet[i];
                        }
                        MyHxWriters[0].WriteLine((Single)packet.MsgTimeStamp, data);

                    }
                }
            }
            catch (NullReferenceException ex)
            {
                DataProcessingError.Add("HoneyxLogger.cs", "File does not exist", ex.ToString());
            }
        }

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