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

namespace iSTP_DataProcessing
{
    /// <summary>
    /// HX writer.
    /// </summary>
    public class HoneyxWriter
    {
        #region Public Global values
        /// <summary>
        /// returns limit for writing in hx iFile.
        /// </summary>
        public static int WriteLimit { get { return 200; } }
        public HoneyXIO_File HxFile = new HoneyXIO_File();

        public const int HoneyXIO_constantTime = 0;
        public const int HoneyXIO_varyingTime = 1;

        public const int HoneyXIO_singleTimeSingleData = 1;
        public const int HoneyXIO_singleTimeDoubleData = 2;
        public const int HoneyXIO_doubleTimeSingleData = 5;
        public const int HoneyXIO_doubleTimeDoubleData = 6;
        #endregion

        #region Private global values
        private Boolean onlyOnce = false; /// <summary>Value for write header only once</summary>
        private const int HX_labelKey = 0x4D;
        private const int HX_infoKey = 0x4C;
        private const int HX_noKey = 0xFF;
        private const int HX_labelOnLine = 4;
        private const int HX_stdioBufSize = 0x1000;
        private const string HX_timeLabel = "time ";

        private static long HX_filesCurrentlyOpen = 0;

        private Int32 BytesCounter = 0;

        private String filenameBinary = null;

        private int ProvidesColicion = 0;

        static private Int32 index = 0;
        static private Int32 index_real = 0;
        #endregion

        #region Public global values
        public const int HoneyXIO_infoString = 0;
        public const int HoneyXIO_infoFloat = 1;
        public const int HoneyXIO_infoDouble = 2;
        #endregion

        #region Enums & Structures
        private struct InternalData
        { 
            public Double time;
            public Double[] outData;
            public HoneyXIO_File file;
            public Int32 index;
        }

        public enum HoneyXIO_ErrorType
        {
            HoneyXIO_fileHasNotBeenInitialized,
            HoneyXIO_fileNotOpened,
            HoneyXIO_OK,
            HoneyXIO_fileDoesNotExist,
            HoneyXIO_endOfFile,
            HoneyXIO_notAHoneyXFile,
            HoneyXIO_unknownError,
            HoneyXIO_cannotAccessFile,
            HoneyXIO_cannotWriteToFile,
            HoneyXIO_incorrectLabels,
            HoneyXIO_fileDoesNotHaveTime,
            HoneyXIO_movedToEndOfFile,
            HoneyXIO_fileDoesNotHaveAnyData,
            HoneyXIO_insufficientStorage,
            HoneyXIO_lengthOfALineIsIncorrect,
            HoneyXIO_incorrectNumberOfLabels,
            HoneyXIO_cannotWriteInfoData,
            HoneyXIO_illegalFileMode,
            HoneyXIO_cannotAppendDataToFile
        }

        public struct HoneyXIO_infoType
        {
            public int designator;     //type of data;HoneyXIO_infoString = 0, HoneyXIO_infoFloat = 1, HoneyXIO_infoDouble = 2 
            public string variable;   //string with variable name
            public int columns;	      //number of iColumns, in case of string data it is iLength of the string	
            public int rows;           //number of iRows, in case of string data this field is ignored
            public string strData;      //pointer to string data, in case of double or float data this field is ignored
            public float[] floatData;   //pointer to float data array, in case of double or string data this field is ignored
            public double[] doubleData; //pointer to double data array, in case of float or string data this field is ignored
        } ;

        /* -------------------------------------------------------------------------- */
        /* HoneyX header record */
        /* -------------------------------------------------------------------------- */
        public struct HoneyXIO_File
        {
            public HoneyXIO_ErrorType error;
            public HoneyXIO_HeaderType header;
            public long startOfDataFileLocation;
            public long previousDataFileLocation;
            public long fileMode;
            public long delimeterCharSize;
            public long timeSize;
            public long dataSize;
            public long linesInFile;
            public long endOfFilePosition;
            // Variables related to the complex _info processing
            public long lengthFieldPosition; // complexInfo write phase - to be able to go back and write correct iLength
            public long elementDataLength; // current complexInfo element iLength
            public int complexInfo; //Does it contain complexInfo? 1 - yes, 0 - no - read phase
            public long complexInfoEndPos; // compexInfo end position
            public long complexInfoStartPos; // compexInfo start position
            public long posAfterOpen; // need to go back to this postion once reading of complex _info is finished

            public double startTime;
            public double currentTime;
            public double pastTime;
            public double deltaTime;
            public double endTime;
            public long itemsOnLine; /* including delimeters, iTime, and data */
            public long isForeignEndian;
            public long isOpenedForWriting;
            public BinaryWriter wFile;
            public string filename;
            public char[] labels;
            public char[] info;
            public long infoLineSize;
            public long numberOfLabels;
            public long stdioBuf; /* Buffer ptr passed to setvbuf(...) */
        };

        public struct HoneyXIO_HeaderType
        {
            public long rows;
            public long columns;
            public int mode;
            public int dataType;
        }

        #endregion

        #region Constructors & Destructor
        /// <summary>
        /// Initialization honeyx iFile
        /// </summary>
        /// <param name="iFileName">name of iFile</param>
        public HoneyxWriter(String iFileName)
        {
            InitFileStruct();
            OpenFile(iFileName);
        }

        /// <summary>
        /// Close honeyx iFile
        /// </summary>
        ~HoneyxWriter()
        {
            try
            {
                if (HxFile.wFile != null)
                {
                    CloseFile_private();
                }
            }
            catch (Exception ex)
            {
                DataProcessingError.Add("HoneyxWriter.cs", "HoneyxWriter class: Error occurs during disposing HoneyxClass", ex.ToString());
            }
            finally
            {
                GC.Collect();
            }
        }
        #endregion

        #region Private Sector
        /// <summary>
        /// Initialization HoneyXIO_File structure
        /// </summary>
        /// <param name="iFile"></param>
        protected void InitFileStruct()
        {
            HxFile = new HoneyXIO_File() 
            { 
                error = HoneyXIO_ErrorType.HoneyXIO_fileNotOpened, 
                currentTime = 0.0d, 
                pastTime = 0.0d, 
                deltaTime = 0.0d, 
                delimeterCharSize = sizeof(long) 
            };
        }
        /// <summary>
        /// Converts string to byte array
        /// </summary>
        /// <param name="iSource">String iSource</param>
        /// <param name="iSourceOffset">Offset for string iSource, starting index</param>
        /// <param name="iDestination">reference to iDestination array</param>
        /// <param name="iDestinationOffset">Offset for string iSource, starting index</param>
        private void ConvertStringToBytes(String iSource, Int32 iSourceOffset, ref Byte[] iDestination, Int32 iDestinationOffset)
        {
            Char[] _charBuff = iSource.ToCharArray();
            iDestination = new Byte[_charBuff.Length];
            Buffer.BlockCopy(_charBuff, iSourceOffset, iDestination, iDestinationOffset, _charBuff.Length);
            Byte[] _desBuff = iDestination;
            iDestination = new Byte[_desBuff.Length + 8];
            iDestination[0] = (byte)((_desBuff.Length & (255 << 24)) >> 24);
            iDestination[1] = (byte)((_desBuff.Length & (255 << 16)) >> 16);
            iDestination[2] = (byte)((_desBuff.Length & (255 << 8)) >> 8);
            iDestination[3] = (byte)((_desBuff.Length & (255 << 0)) >> 0);
            for (int i = 4; i < _desBuff.Length; i++)
                iDestination[i] = _desBuff[i - 4];
            iDestination[_desBuff.Length] = (byte)((_desBuff.Length & (255 << 24)) >> 24);
            iDestination[_desBuff.Length + 1] = (byte)((_desBuff.Length & (255 << 16)) >> 16);
            iDestination[_desBuff.Length + 2] = (byte)((_desBuff.Length & (255 << 8)) >> 8);
            iDestination[_desBuff.Length + 3] = (byte)((_desBuff.Length & (255 << 0)) >> 0);
        }

        
        /// <summary>
        /// Opens honeyx file
        /// </summary>
        /// <param name="iFileName">name of iFile</param>
        /// <returns></returns>
        protected Boolean OpenFile(String iFileName)
        {
            Boolean _result = false;

            HxFile.filename = iFileName;
            filenameBinary = iFileName;
            HxFile.wFile = null;
            HxFile.wFile = new BinaryWriter(File.Open(HxFile.filename, FileMode.Create, FileAccess.Write));
            if (HxFile.wFile != null)
                _result = true;

            return _result;
        }
        /// <summary>
        /// Writes data in honeyx iFile
        /// </summary>
        /// <param name="iData">data</param>
        private void Write(Single[] iData)
        {
            BytesCounter += iData.Length * sizeof(float);
            if (HxFile.wFile != null)
            {
                foreach (Single x in iData)
                {
                    HxFile.wFile.Write(x);
                }
            }
        }
        /// <summary>
        /// Writes data in honeyx iFile
        /// </summary>
        /// <param name="iData">data</param>
        private void Write(Double[] iData)
        {
            BytesCounter += iData.Length * sizeof(double);
            if (HxFile.wFile != null)
            {
                foreach (Double x in iData)
                {
                    HxFile.wFile.Write(x);
                }
            }
        }
        /// <summary>
        /// Writes data in honeyx iFile
        /// </summary>
        /// <param name="iData">data</param>
        private void Write(String iData)
        {
            Char[] _charBuff = iData.ToCharArray();
            BytesCounter += _charBuff.Length;
            if (HxFile.wFile != null)
            {
                foreach (Char x in _charBuff)
                {
                    HxFile.wFile.Write(x);
                    HxFile.wFile.Flush();
                }
            }
        }
        /// <summary>
        /// Writes data in honeyx iFile
        /// </summary>
        /// <param name="iData">data</param>
        private void Write(Int32 iData)
        {
            BytesCounter += 4;
            if (HxFile.wFile != null)
                HxFile.wFile.Write(iData);
        }
        /// <summary>
        /// Writes data in honeyx iFile
        /// </summary>
        /// <param name="iData">data</param>
        private void Write(Single iData)
        {
            BytesCounter += 4;
            if (HxFile.wFile != null)
            {
                HxFile.wFile.Write(iData);
                HxFile.wFile.Flush();
            }
        }
        /// <summary>
        /// Writes data in honeyx iFile
        /// </summary>
        /// <param name="iData">data</param>
        private void Write(Double iData)
        {
            BytesCounter += 8;
            if (HxFile.wFile != null)
            {
                HxFile.wFile.Write(iData);
            }
        }
        /// <summary>
        /// Writes data in honeyx iFile
        /// </summary>
        /// <param name="iData">data</param>
        private void Write(Char iData)
        {
            BytesCounter++;
            if (HxFile.wFile != null)
            {
                HxFile.wFile.Write((byte)iData);
                HxFile.wFile.Flush();
            }
        }
        /// <summary>
        /// Close honeyx iFile and sets iFile.wFile to null
        /// </summary>
        private void CloseFile_private()
        {
            if (HxFile.wFile != null)
            {
                HxFile.wFile.Close();
                HxFile.wFile = null;
            }
        }

        /// <summary>
        /// Writes header for complex _info into Honeyx iFile
        /// </summary>
        /// <param name="iLength">Info iLength</param>
        /// <returns></returns>
        private Boolean StartComplexInfo(Int32 iLength)
        {
            const int _labelBytesOnLine = 4;
            int _infoID = HX_infoKey;

            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                if (HxFile.linesInFile > 0)
                {
                    HxFile.error = HoneyXIO_ErrorType.HoneyXIO_cannotWriteInfoData;
                    return false;
                }
                else
                {
                    /* Write label id */
                    Write(_labelBytesOnLine);
                    Write(_infoID);
                    Write(_labelBytesOnLine);
                    /* Store position where iLength is stored so we can go back later and update it  */
                    /* Write iLength of complex _info - need to go back to this point at 
                       the end of complexInfo write and update it  */
                    Write(iLength);
                    BytesCounter = 0;
                }
            }
            return true;
        }

        /// <summary>
        /// Writes _info into Honeyx iFile
        /// </summary>
        /// <param name="iHoneyXIO_infoStructure">Type of _info</param>
        /// <returns>TRUE - success, FALSE - _error</returns>
        private Boolean WriteComplexInfoElement(HoneyXIO_infoType iHoneyXIO_infoStructure)
        {
            char _nullChar = '\0';
            const string _desnullString = "\0\0\0";
            char _sChar = 'S';
            char _dChar = 'D';
            char _fChar = 'F';
            const int _oneRow = 1;
            char[] _desnull = _desnullString.ToCharArray();

            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                if (HxFile.linesInFile > 0)
                {
                    HxFile.error = HoneyXIO_ErrorType.HoneyXIO_cannotWriteInfoData;
                    return false;
                }
                else
                {
                    switch (iHoneyXIO_infoStructure.designator)
                    {
                        //HoneyXIO_infoString  
                        case HoneyXIO_infoString:
                            //write designator
                            Write(_desnull[0]);
                            Write(_desnull[0]);
                            Write(_desnull[0]);
                            Write(_sChar);
                            //write number of iRows
                            Write(_oneRow);
                            //write number of iColumns
                            Write(iHoneyXIO_infoStructure.strData.Length);
                            //write variable name
                            Write(iHoneyXIO_infoStructure.variable);
                            Write(_nullChar);
                            //write string data
                            Write(iHoneyXIO_infoStructure.strData);
                            break;
                        //HoneyXIO_infoFloat
                        case HoneyXIO_infoFloat:
                            //write designator
                            Write(_desnull[0]);
                            Write(_desnull[0]);
                            Write(_desnull[0]);
                            Write(_fChar);
                            //write number of iRows
                            Write(iHoneyXIO_infoStructure.rows);
                            //write number of iColumns
                            Write(iHoneyXIO_infoStructure.columns);
                            //write variable name
                            Write(iHoneyXIO_infoStructure.variable);
                            Write(_nullChar);
                            //write float data
                            Write(iHoneyXIO_infoStructure.floatData);
                            break;
                        //HoneyXIO_infoDouble
                        case HoneyXIO_infoDouble:
                            //write designator
                            Write(_desnull[0]);
                            Write(_desnull[0]);
                            Write(_desnull[0]);
                            Write(_dChar);
                            //write number of iRows
                            Write(iHoneyXIO_infoStructure.rows);
                            //write number of iColumns
                            Write(iHoneyXIO_infoStructure.columns);
                            //write variable name
                            Write(iHoneyXIO_infoStructure.variable);
                            Write(_nullChar);
                            //write double data
                            Write(iHoneyXIO_infoStructure.doubleData);
                            break;
                        default:
                            return false; // Unknown iHoneyXIO_infoStructure.designator _value
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// Write footer for complex _info
        /// </summary>
        /// <returns>TRUE - success, FALSE - _error</returns>
        private Boolean FinishComplexInfo()
        {
            char _nullChar = '\0';
            long _length;

            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                if (HxFile.linesInFile > 0)
                {
                    HxFile.error = HoneyXIO_ErrorType.HoneyXIO_cannotWriteInfoData;
                    return false;
                }
                else
                {
                    _length = BytesCounter;
                    _length++;
                    //write null char at the end of the data field
                    Write(_nullChar);
                    //write the iLength at the end
                    Write((int)_length);
                }
            }
            return true;
        }

        /// <summary>
        /// Writes header into honeyx iFile
        /// </summary>
        private void WriteHeader()
        {
            const int _HXheaderBytesOnLine = 16;
            int[] _HXheader = new int[] { 1, 1, 1, 6 };

            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                _HXheader[0] = (int)HxFile.header.rows;
                _HXheader[1] = (int)HxFile.header.columns;
                _HXheader[2] = HxFile.header.mode;
                _HXheader[3] = HxFile.header.dataType;

                /* Write the header */
                Write(_HXheaderBytesOnLine);
                Write(_HXheader[0]);
                Write(_HXheader[1]);
                Write(_HXheader[2]);
                Write(_HXheader[3]);
                Write(_HXheaderBytesOnLine);
            }
        }

        /// <summary>
        /// Function sets size of type for iTime and data into iFile struct
        /// </summary>
        /// <param name="iDataType">Number of iMode</param>
        /// <returns></returns>
        private HoneyXIO_ErrorType SetFileDataType(int iDataType)
        {
            HoneyXIO_ErrorType _error = HoneyXIO_ErrorType.HoneyXIO_OK;

            switch (iDataType)
            {
                case HoneyXIO_singleTimeSingleData:
                    HxFile.timeSize = sizeof(float);
                    HxFile.dataSize = sizeof(float);
                    break;
                case HoneyXIO_singleTimeDoubleData:
                    HxFile.timeSize = sizeof(float);
                    HxFile.dataSize = sizeof(double);
                    break;
                case HoneyXIO_doubleTimeSingleData:
                    HxFile.timeSize = sizeof(double);
                    HxFile.dataSize = sizeof(float);
                    break;
                case HoneyXIO_doubleTimeDoubleData:
                    HxFile.timeSize = sizeof(double);
                    HxFile.dataSize = sizeof(double);
                    break;
                default:
                    HxFile.timeSize = sizeof(double);
                    HxFile.dataSize = sizeof(double);
                    _error = HoneyXIO_ErrorType.HoneyXIO_notAHoneyXFile;
                    break;
            }
            if (HxFile.header.mode == HoneyXIO_constantTime)
            {
                HxFile.timeSize = 0;
            }

            return (_error);
        }
        #endregion

        #region Public Sector
        /// <summary>
        /// Flush data from windows writes iData
        /// </summary>
        public void FlushFileBuffer()
        {
            HxFile.wFile.Flush();
        }
        /// <summary>
        /// Flush data and close iFile
        /// </summary>
        public void CloseFile()
        {
            try
            {
                FlushFileBuffer();
                CloseFile_private();
                onlyOnce = false;
            }
            catch (Exception ex)
            {
                DataProcessingError.Add("HoneyxWriter.cs", string.Format("HoneyxWriter class: Error occurs during closing honeyx file ({0})", HxFile.filename), ex.ToString());
            }
            finally
            {
                GC.Collect();
            }
        }

        /// <summary>
        /// Creates Honeyx iFile with input parameters
        /// </summary>
        /// <param name="iDataType">Type of iTime and data (double, double) or (double, single)</param>
        /// <param name="iRows">Number of iRows for iColumns names</param>
        /// <param name="iColumns">Number of iColumns, has to be equal to number of iLabels</param>
        /// <param name="iLabels">Columns names included in this iText, space delimiter is between names</param>
        /// <param name="iFilename">Files name ending .hx</param>
        public void CreateFileWithLabels
                            (int iDataType,
                             long iRows,
                             long iColumns,
                             string iLabels)
        {
            var _length = 0;
            var _totalLength = 0;
            var _timeLength = 0;

            const long _labelBytesOnLine = 4;
            long[] _labelHeader = new long[] { HX_labelKey };

            string _labelString = null;
            char[] _fileModeStr = new char[5];

            _fileModeStr[0] = '\0';

            HxFile.header.rows = iRows;
            HxFile.header.columns = iColumns;
            HxFile.header.mode = HoneyXIO_varyingTime;
            HxFile.header.dataType = iDataType;
            HxFile.fileMode = 1L;

            HxFile.error = SetFileDataType(iDataType);
            const long _localVar = 2;
            HxFile.itemsOnLine = _localVar + HxFile.header.rows * HxFile.header.columns;
            if (HxFile.header.mode == HoneyXIO_varyingTime)
            {
                HxFile.itemsOnLine++;
            }

            HxFile.isOpenedForWriting = 1;
            /* write the label line */
            HX_filesCurrentlyOpen++;
            HxFile.error = HoneyXIO_ErrorType.HoneyXIO_OK;

            /* Write the iLabels if they exist */
            /* Write Label code */
            Write((int)_labelBytesOnLine);
            Write((int)0x4D);
            Write((int)_labelBytesOnLine);

            _labelString = iLabels;
            HxFile.numberOfLabels = _labelString.Split(' ').Length;

            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                if (iColumns == HxFile.numberOfLabels)
                {
                    _length = _labelString.ToCharArray().Length;
                    _timeLength = HX_timeLabel.ToCharArray().Length;
                    _totalLength = _length + _timeLength;
                    Write((int)_totalLength);
                    Write(HX_timeLabel);
                    Write(_labelString);
                    Write((int)_totalLength);
                }
                else if (iColumns + 1 == HxFile.numberOfLabels) /* iTime included with iLabels */
                {
                    _length = _labelString.ToCharArray().Length;
                    _totalLength = _length;
                    Write(_totalLength);
                    Write(_labelString);
                    Write(_totalLength);
                }
                else
                {
                    HxFile.error = HoneyXIO_ErrorType.HoneyXIO_incorrectLabels;
                }
            }

            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_incorrectLabels)
            {
                Console.WriteLine("HoneyxWriter class: Incorrect labels for " + HxFile.filename);
            }
        }

        /// <summary>
        /// Writes configure iText into Honeyx file
        /// </summary>
        /// <param name="iText">Configure iText</param>
        /// <returns></returns>
        public void WriteConfigurationText(String iText)
        {
            Int32 _length = 0;

            HoneyxWriter.HoneyXIO_infoType _info = new HoneyxWriter.HoneyXIO_infoType() 
                                                    { 
                                                        designator = HoneyxWriter.HoneyXIO_infoString, 
                                                        rows = 0, 
                                                        strData = iText, 
                                                        columns = iText.Length, 
                                                        variable = "CalData" 
                                                    };

            _length = sizeof(Char) * 5 + sizeof(Int32) + _info.variable.Length + iText.Length;

            StartComplexInfo( _length);
            WriteComplexInfoElement(_info);
            FinishComplexInfo();
        }

        /// <summary>
        /// Writes data and iTime into creates Honeyx iFile
        /// </summary>
        /// <param name="iTime">Honeyx structure</param>
        /// <param name="iOutData">Array fulls of users data</param>
        /// <returns></returns>
        public void WriteLine(Double iTime, Double[] iOutData)
        {
            long _bytesOnLine;
            long _i;
            long _itemsToWrite = HxFile.header.rows * HxFile.header.columns;
            long _j, _k;
            HxFile.pastTime = HxFile.currentTime;
            HxFile.currentTime = iTime;
            HxFile.deltaTime = HxFile.currentTime - HxFile.pastTime;
            _bytesOnLine = HxFile.timeSize + _itemsToWrite * HxFile.dataSize;
            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                //if (HxFile.linesInFile == 0)
                if (onlyOnce == false)
                {
                    onlyOnce = true;
                    WriteHeader();
                    HxFile.startTime = iTime;
                }
                HxFile.endTime = iTime;

                Write((int)_bytesOnLine);
                if (HxFile.header.mode == HoneyXIO_varyingTime)
                {
                    Write(iTime);
                }
                _j = 0;
                _k = 0;
                // Previously code existed here to determine the precision of the input data here
                // by looking at the HxFile.header.iDataType, which is the precision of the data
                // as it is stored in the HxFile.
                // In most cases the input data is actually double precision, even if the HxFile is to be written as
                // single precision.  For that reason, the input data is always assumed to be double precision
                for (_i = 0; _i < iOutData.Length; _i++)
                {
                    Write(iOutData[_i]);
                    _j++;
                    if (_j >= HxFile.header.rows)
                    {
                        _j = 0;
                        _k++;
                    }
                }
                Write((int)_bytesOnLine);
            }
        }

        /// <summary>
        /// Writes data and iTime into creates Honeyx iFile
        /// </summary>
        /// <param name="iTime">Honeyx structure</param>
        /// <param name="iOutData">Array fulls of users data</param>
        /// <returns></returns>
        public void WriteLine(Single iTime, Single[] iOutData)
        {
            long _bytesOnLine;
            long _i;
            long _itemsToWrite = HxFile.header.rows * HxFile.header.columns;
            long _j, _k;
            HxFile.pastTime = HxFile.currentTime;
            HxFile.currentTime = iTime;
            HxFile.deltaTime = HxFile.currentTime - HxFile.pastTime;
            _bytesOnLine = HxFile.timeSize + _itemsToWrite * HxFile.dataSize;
            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                //if (HxFile.linesInFile == 0)
                if (onlyOnce == false)
                {
                    onlyOnce = true;
                    WriteHeader();
                    HxFile.startTime = iTime;
                }
                HxFile.endTime = iTime;

                Write((int)_bytesOnLine);
                if (HxFile.header.mode == HoneyXIO_varyingTime)
                {
                    Write(iTime);
                }
                _j = 0;
                _k = 0;
                // Previously code existed here to determine the precision of the input data here
                // by looking at the HxFile.header.iDataType, which is the precision of the data
                // as it is stored in the HxFile.
                // In most cases the input data is actually double precision, even if the HxFile is to be written as
                // single precision.  For that reason, the input data is always assumed to be double precision
                for (_i = 0; _i < iOutData.Length; _i++)
                {
                    Write(iOutData[_i]);
                    _j++;
                    if (_j >= HxFile.header.rows)
                    {
                        _j = 0;
                        _k++;
                    }
                }
                Write((int)_bytesOnLine);
            }
        }

        /// <summary>
        /// Writes data and iTime into creates Honeyx iFile
        /// </summary>
        /// <param name="iTime">Honeyx structure</param>
        /// <param name="iOutData">Array fulls of users data</param>
        /// <returns></returns>
        public void WriteLine(Double iTime, Single[] iOutData)
        {
            long _bytesOnLine;
            long _i;
            long _itemsToWrite = HxFile.header.rows * HxFile.header.columns;
            long _j, _k;
            HxFile.pastTime = HxFile.currentTime;
            HxFile.currentTime = iTime;
            HxFile.deltaTime = HxFile.currentTime - HxFile.pastTime;
            _bytesOnLine = HxFile.timeSize + _itemsToWrite * HxFile.dataSize;
            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                //if (HxFile.linesInFile == 0)
                if (onlyOnce == false)
                {
                    onlyOnce = true;
                    WriteHeader();
                    HxFile.startTime = iTime;
                }
                HxFile.endTime = iTime;

                Write((int)_bytesOnLine);
                if (HxFile.header.mode == HoneyXIO_varyingTime)
                {
                    Write(iTime);
                }
                _j = 0;
                _k = 0;
                // Previously code existed here to determine the precision of the input data here
                // by looking at the HxFile.header.iDataType, which is the precision of the data
                // as it is stored in the HxFile.
                // In most cases the input data is actually double precision, even if the HxFile is to be written as
                // single precision.  For that reason, the input data is always assumed to be double precision
                for (_i = 0; _i < iOutData.Length; _i++)
                {
                    Write(iOutData[_i]);
                    _j++;
                    if (_j >= HxFile.header.rows)
                    {
                        _j = 0;
                        _k++;
                    }
                }
                Write((int)_bytesOnLine);
            }
        }

        /// <summary>
        /// Writes data and iTime into creates Honeyx iFile
        /// </summary>
        /// <param name="iTime">Honeyx structure</param>
        /// <param name="iOutData">Array fulls of users data</param>
        /// <returns></returns>
        public void WriteLine(Double iTime, List<Single> iOutData)
        {
            long _bytesOnLine;
            int _i;
            long _itemsToWrite = HxFile.header.rows * HxFile.header.columns;
            long _j, _k;
            HxFile.pastTime = HxFile.currentTime;
            HxFile.currentTime = iTime;
            HxFile.deltaTime = HxFile.currentTime - HxFile.pastTime;
            _bytesOnLine = HxFile.timeSize + _itemsToWrite * HxFile.dataSize;
            if (HxFile.error == HoneyXIO_ErrorType.HoneyXIO_OK)
            {
                //if (HxFile.linesInFile == 0)
                if (onlyOnce == false)
                {
                    onlyOnce = true;
                    WriteHeader();
                    HxFile.startTime = iTime;
                }
                HxFile.endTime = iTime;

                Write((int)_bytesOnLine);
                if (HxFile.header.mode == HoneyXIO_varyingTime)
                {
                    Write(iTime);
                }
                _j = 0;
                _k = 0;
                // Previously code existed here to determine the precision of the input data here
                // by looking at the HxFile.header.iDataType, which is the precision of the data
                // as it is stored in the HxFile.
                // In most cases the input data is actually double precision, even if the HxFile is to be written as
                // single precision.  For that reason, the input data is always assumed to be double precision
                for (_i = 0; _i < iOutData.Count; _i++)
                {
                    Write(iOutData[_i]);
                    _j++;
                    if (_j >= HxFile.header.rows)
                    {
                        _j = 0;
                        _k++;
                    }
                }
                Write((int)_bytesOnLine);
            }
        }

        #endregion;
    }
}
