using Converters;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Threading;



namespace VSview
{
    public class DetectorCommunication : BaseViewModel
    {

        #region Constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        public DetectorCommunication() { }

        /// <summary>
        /// Main constructor for serial port 
        /// </summary>
        public DetectorCommunication(Detector detector)
        {
            Detector = detector;

            CommunicationList = new CommunicationList();
        }

        #endregion


        /// <summary>
        /// Collection of all commands and enquiries
        /// </summary>
        public CommunicationList CommunicationList { get; set; }




        #region Private members

        //reference to Detector
        private Detector Detector;

        //serial port
        private SerialPort port;

        // Send queue - stores messages to be sent to the detector in queue
        public LinkedList<Message> SendQueue;

        //queue of received string from detector serial port
        private LinkedList<List<string>> RecvQueue;

        //Thread managing        
        private bool _ComThreadWorking = true;

        //Serial communication thread
        private Thread SerialThread;

        //Message parsing tread
        private Thread ParsingThread;

        //List of strings received from detector
        private List<string> Recvmessage;

        //Timer for cyclic data enquiring - cycling command sending to detector according to actual selected tabitem
        private System.Timers.Timer GetDataTimer;

        //Timer used in serial communication - if overflown - detector didnt respond in time
        private System.Timers.Timer RecvTimeout;

        //Timer for cyclic leakrate and test port pressure enquiring
        private System.Timers.Timer LPVTimer;

        private bool Initialization = false;

        //lock
        private object _lock = new object();
        #endregion

        #region Helper private members
        //Helper string for reading line from serial port
        private string ReceivedData;

        //Helper bool for serial communication control - commands are sent only if this is true
        private bool responseRecv = true;

        //Helper list of recieved string belonging to single response
        private List<string> ReceivedDataList;

        //Helper variable used for storing message from output queue
        private Message message;

        //Helper character fields - trimming end of messages and finding number in string 
        private char[] numbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-' };
        private char[] ending = { '\r', ' ', 'o', 'k' };

        #endregion

        #region Public methods



        /// <summary>
        /// Method for connection to selected port
        /// </summary>
        /// <param name="portName"> name of port to be connected </param>
        /// <returns></returns>
        public void OpenSerial(string portName)
        {
            if (port == null || !port.IsOpen)
            {
                TerminalViewModel.WriteToLog("Connecting to serial port " + portName);


                //Test port for detector pressence
                if (TestPort(portName, out string DetectorType))
                {
                    //Make note in log about connecting
                    TerminalViewModel.WriteToLog(port.PortName + " is connected");
                    TerminalViewModel.WriteToLog("Detector type resolved as " + DetectorType);
                    //Start serial communication with detector
                    StartSerialCommunication();
                    //Notify view of succesfull connetion
                    Detector.Settings.IsConnected = true;
                    SettingViewModel.DetectorIndex = SettingViewModel.DetectorTypes.IndexOf(DetectorType);
                    SettingViewModel.PortIndex = SettingViewModel.SerialPorts.IndexOf(portName);
                }
                else
                {
                    TerminalViewModel.WriteToLog("Serial port " + port.PortName + " could not be connected");
                }

            }

        }

        /// <summary>
        /// Method for disconecting from serial port
        /// </summary>
        public void CloseSerial()
        {
            new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;

                if (port != null && port.IsOpen)
                {
                    TerminalViewModel.WriteToLog("Disconnecting from serial port " + port.PortName);

                    StopSerialCommunication();
                }
            }).Start();
        }

        /// <summary>
        /// Method for autodetection of used port
        /// </summary>
        public void Autodetection()
        {
            if (port == null || !port.IsOpen)
            {
                new Thread(() =>
                {
                    List<string> ports = SettingViewModel.ScanPorts();

                    if (ports.Count > 0)
                    {

                        Thread.CurrentThread.IsBackground = true;

                        TerminalViewModel.WriteToLog("Connecting...");
                        //Try each awailiable port
                        foreach (string portName in ports)
                        {
                            OpenSerial(portName);
                            if (port.IsOpen)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        TerminalViewModel.WriteToLog("No port for connection is available");
                    }
                }).Start();
            }
            else
            {
                TerminalViewModel.WriteToLog(port.PortName + " is connected");
            }
        }

        #endregion

        #region Private methods   

        /// <summary>
        /// Method for testing port communication
        /// </summary>
        /// <param name="Port">port to be tested</param>
        /// <returns></returns>
        private bool TestPort(string portName, out string DetectorType)
        {
            try
            {
                //Initialize serial port
                port = new SerialPort                   //create new serial port
                {
                    PortName = portName,     //Set portname according to selection   
                    BaudRate = 9600,        //COM port baud rate
                    Handshake = Handshake.None,     // disable handshake
                    Parity = Parity.None,        // no parity
                    DataBits = 8,        // 8 data bits
                    StopBits = StopBits.One,         // one stop bit          
                    ReadTimeout = 3000,      // time allowed to read data
                    WriteTimeout = 100,      // time allowed to send data  
                };

                port.Open();
                port.Write("?CALOK\r");
                Thread.Sleep(100);
                string rec_data = port.ReadLine();
                if (!String.IsNullOrEmpty(rec_data))
                {
                    if (rec_data.Contains("#?"))
                        DetectorType = "VS-C15";
                    else
                        DetectorType = "VS-PR";
                    return true;
                }
                else
                {
                    throw new TimeoutException();
                }
            }
            catch (Exception ex)
            {
                port.Close();
                DetectorType = string.Empty;
                return false;
            }
        }

        /// <summary>
        /// Method for starting serial communication
        /// </summary>
        private void StartSerialCommunication()
        {
            try
            {
                //Initialize queues
                SendQueue = new LinkedList<Message>();
                RecvQueue = new LinkedList<List<string>>();

                _ComThreadWorking = true;

                //Initialize thread
                SerialThread = new Thread(SerialReadWrite);
                SerialThread.IsBackground = true;
                SerialThread.Start();

                ParsingThread = new Thread(ProcessSerialData);
                ParsingThread.IsBackground = true;
                ParsingThread.Start();

                //Initialize parsing thread

                //timer for checking if message was received in time
                RecvTimeout = new System.Timers.Timer();
                RecvTimeout.Interval = 3000;
                RecvTimeout.Elapsed += RecvTimeout_Elapsed; ;

                //timer for cyclic data requesting
                GetDataTimer = new System.Timers.Timer();
                GetDataTimer.Interval = 5000;
                GetDataTimer.Elapsed += GetDataTimer_Elapsed; ;
                GetDataTimer.Start();

                //Timer for leak rate data request
                LPVTimer = new System.Timers.Timer();
                LPVTimer.Interval = 500;
                LPVTimer.Elapsed += LPVTimer_Elapsed; ;
                LPVTimer.Start();

                Initialization = true;
            }
            catch (Exception ex) { MessageBox.Show("Error ocurred during detector serial communication incitialization /nReason: " + ex.Message, "Serial error", MessageBoxButton.OK, MessageBoxImage.Warning); }
        }

        /// <summary>
        /// Method for stopping serial communication
        /// </summary>
        private void StopSerialCommunication()
        {
            try
            {
                //stop serial thread
                _ComThreadWorking = false;

                //stop all timers
                RecvTimeout.Stop();
                RecvTimeout = null;
                GetDataTimer.Stop();
                GetDataTimer = null;
                LPVTimer.Stop();
                LPVTimer = null;

                //Clear serial send queue
                if (SendQueue.Count > 0)
                    SendQueue.Clear();
                SendQueue = null;

                //Cleare serial recv queue
                if (RecvQueue.Count > 0)
                    RecvQueue.Clear();
                RecvQueue = null;

                //clear port read buffer
                if (port.BytesToRead > 0)
                    port.DiscardInBuffer();

                //Clear port write buffer
                if (port.BytesToWrite > 0)
                    port.DiscardOutBuffer();

                //Wait before closing port after erasing buffers
                Thread.Sleep(200);

                //Close serial port
                port.Close();

                Detector.Settings.IsConnected = false;

            }
            catch (Exception ex) { MessageBox.Show("Error ocurred during detector serial communication incitialization /nReason: " + ex.Message, "Serial error", MessageBoxButton.OK, MessageBoxImage.Warning); }

        }

        /// <summary>
        /// Method for reseting serial communication
        /// </summary>
        private void ResetSerial()
        {

        }

        /// <summary>
        /// Method for sending data to the serial port
        /// </summary>
        private void SerialReadWrite()
        {
            while (_ComThreadWorking)
            {
                try
                {
                    if (Detector.Settings.IsConnected)          //Check if COM port is connected
                    {

                        #region writing
                        if (SendQueue.Count > 0 & responseRecv)
                        {
                            // set flag to false - prevent sending other messages before receiveing echo back 
                            responseRecv = false;

                            //Get first message in queue
                            message = SendQueue.First();

                            //remove first message
                            SendQueue.RemoveFirst();

                            if (message.ShowInLog)
                                TerminalViewModel.WriteToLog(message.Command);

                            //get array of bytes representing message
                            byte[] hexstring = Encoding.ASCII.GetBytes(message.Command);

                            //write array to serial port
                            port.Write(hexstring, 0, hexstring.Length);

                            //end string with CR 
                            port.Write("\r");
                        }
                        #endregion


                        #region reading
                        if (port.BytesToRead > 0)         // if port have some bytes to be read
                        {
                            // read one line of data  
                            ReceivedData = port.ReadLine().Trim('\r');

                            // check if command was sent
                            if (ReceivedData.Contains(message.Command))
                                ReceivedDataList = new List<string>();

                            // check if message should be written to the console
                            if (message.ShowInLog)
                                TerminalViewModel.WriteToLog(ReceivedData);

                            // add message to list 
                            if (!ReceivedData.Contains("#?"))
                                ReceivedDataList.Add(ReceivedData);

                            // if end of message was received, enque list of received string to the fifo
                            if (ReceivedData.Contains("ok") || ReceivedData.Contains("#?"))
                            {
                                RecvQueue.AddLast(ReceivedDataList);
                                responseRecv = true;
                            }
                        }

                        if (!responseRecv)
                            RecvTimeout.Start(); //start timeout timer
                        else
                            RecvTimeout.Stop(); // stop timeout timer                
                    }
                    #endregion
                    else
                    {
                        Thread.Sleep(1); // sleep for 1ms
                    }
                }
                catch (Exception ex)
                {
                    ResetSerial();
                }
            }
        }



        /// <summary>
        /// Processes serial data from detector
        /// All received data are processed and stored in databinding collection for UI to update
        /// </summary>
        private void ProcessSerialData()
        {
            string Temp = "";
            while (_ComThreadWorking)
            {
                try
                {
                    if (RecvQueue.Count > 0)         //pokud fronta obsahuje neco na precteni
                    {
                        Recvmessage = RecvQueue.First();  // ziskani prvniho prvku (listu) z fronty
                        RecvQueue.RemoveFirst();

                        //ziskani nazvu commandu
                        if (Recvmessage[0] != "")
                        {
                            string CommandName = Recvmessage[0].Substring(0, Recvmessage[0].IndexOf(' '));

                            switch (CommandName)
                            {
                                case ("SERVICE1"):
                                    {

                                        {
                                            Detector.Ionchamber.Voltage = SearchList("IONCHAMBER", Recvmessage);
                                            Detector.Ionchamber.Emission = SearchList("EMISSION", Recvmessage);

                                            Temp = SearchList("OFFSET", Recvmessage).TrimStart(' ');
                                            Detector.Ionchamber.Offset1 = Temp.Substring(0, Temp.IndexOf(' '));
                                            Temp = SearchList("GAIN", Recvmessage).TrimStart(' ');
                                            Detector.Ionchamber.Gain = Temp.TrimEnd(' ');

                                            Detector.Range.Exponent = SearchList("exponent", Recvmessage);
                                            Detector.Range.RangeValue = SearchList("range", Recvmessage, 3);
                                            Detector.Reject.Reject1.Value = SearchList("reject", Recvmessage, 7);
                                            Detector.Reject.Reject2.Value = SearchList("reject", Recvmessage, 7, 8);
                                            Detector.Reject.Reject3.Value = SearchList("reject", Recvmessage, 7, 16);
                                            Detector.Reject.Reject4.Value = SearchList("reject", Recvmessage, 7, 24);
                                            Detector.Reject.RejectA.Value = SearchList("reject", Recvmessage, -1, 32);
                                            Detector.Calibration.InternalTemp = SearchList("Cal Leak Temperature", Recvmessage) + "°C";
                                            Detector.Calibration.InternalLeak = SearchList("stdleak", Recvmessage);
                                            int turboindex = Recvmessage.FindLastIndex(r => r.Contains("Turbo"));
                                            if (turboindex != -1)
                                            {
                                                Detector.Turbo.TurboMode = Recvmessage[turboindex - 4].Substring(6).TrimEnd(ending).TrimStart(' ');
                                                Detector.Turbo.TurboFault = Recvmessage[turboindex - 3].Substring(6).TrimEnd(ending).TrimStart(' ');
                                                Detector.Turbo.TurboSpeed = Recvmessage[turboindex - 2].Substring(19).TrimEnd(ending).TrimStart(' ');
                                                Detector.Turbo.TurboTemp = Recvmessage[turboindex - 1].Substring(21).TrimEnd(ending).TrimStart(' ');
                                                Detector.Turbo.TurboHours = Recvmessage[turboindex].Substring(18).TrimEnd(ending).TrimStart(' ');
                                            }
                                        }
                                        break;
                                    }
                                case ("SERVICE2"):
                                    {
                                        Detector.Calibration.ExternalLeak = SearchList("External Leak", Recvmessage);
                                        Detector.Calibration.InternalFactor = SearchList("Temperature Factor", Recvmessage);
                                        Detector.Settings.AutoZero = SearchListBool("AZ<0", Recvmessage);

                                        int rejectindex = Recvmessage.FindIndex(r => r.Contains("Reject"));

                                        SearchReject(Recvmessage[rejectindex], out bool On, out bool High, out bool Leak);
                                        Detector.Reject.Reject1.State = On;
                                        Detector.Reject.Reject1.IsHigh = High;
                                        Detector.Reject.Reject1.IsLow = !High;
                                        Detector.Reject.Reject1.IsLeak = Leak;
                                        Detector.Reject.Reject1.IsPressure = !Leak;


                                        SearchReject(Recvmessage[rejectindex + 1], out bool On1, out bool High1, out bool Leak1);
                                        Detector.Reject.Reject2.State = On1;
                                        Detector.Reject.Reject2.IsHigh = High1;
                                        Detector.Reject.Reject2.IsLow = !High1;
                                        Detector.Reject.Reject2.IsLeak = Leak1;
                                        Detector.Reject.Reject2.IsPressure = !Leak1;

                                        SearchReject(Recvmessage[rejectindex + 2], out bool On2, out bool High2, out bool Leak2);
                                        Detector.Reject.Reject3.State = On2;
                                        Detector.Reject.Reject3.IsHigh = High2;
                                        Detector.Reject.Reject3.IsLow = !High2;
                                        Detector.Reject.Reject3.IsLeak = Leak2;
                                        Detector.Reject.Reject3.IsPressure = !Leak2;

                                        SearchReject(Recvmessage[rejectindex + 3], out bool On3, out bool High3, out bool Leak3);
                                        Detector.Reject.Reject4.State = On;
                                        Detector.Reject.Reject4.IsHigh = High;
                                        Detector.Reject.Reject4.IsLow = !High;
                                        Detector.Reject.Reject4.IsLeak = Leak;
                                        Detector.Reject.Reject4.IsPressure = !Leak;

                                        SearchReject(Recvmessage[rejectindex + 4], out bool OnA, out bool HighA, out bool LeakA);
                                        Detector.Reject.RejectA.State = On;
                                        Detector.Reject.RejectA.IsHigh = High;
                                        Detector.Reject.RejectA.IsLow = !High;
                                        Detector.Reject.RejectA.IsLeak = Leak;
                                        Detector.Reject.RejectA.IsPressure = !Leak;

                                        Temp = SearchList("Leak Expiration", Recvmessage).Replace(' ', '/');
                                        string format = "M/d/yyyy";
                                        DateTime.TryParseExact(Temp, format, null, DateTimeStyles.None, out DateTime datum);
                                        Detector.Calibration.InternalExpire = datum.ToString("d/M/yyyy");

                                        break;
                                    }
                                case ("?ALL"):
                                    {
                                        Detector.Ionchamber.Voltage = SearchList("IONCHAMBER", Recvmessage);
                                        Detector.Ionchamber.Emission = SearchList("EMISSION", Recvmessage);

                                        Temp = SearchList("OFFSET", Recvmessage).TrimStart(' ');
                                        Detector.Ionchamber.Offset1 = Temp.Substring(0, Temp.IndexOf(' '));
                                        Temp = SearchList("GAIN", Recvmessage).TrimStart(' ');
                                        Detector.Ionchamber.Gain = Temp.Substring(0, Temp.IndexOf(' '));

                                        break;
                                    }
                                case ("?LPV"):
                                    {

                                        Detector.Ionchamber.Leakrate = double.Parse(Recvmessage[0].Substring(5, 8).TrimEnd(ending), CultureInfo.InvariantCulture);

                                        string tp = Recvmessage[0].Substring(Recvmessage[0].IndexOf(" ", 6) + 1, 6).TrimStart('0');

                                        if (!string.IsNullOrEmpty(tp))
                                        {
                                            Detector.Ionchamber.TPpressure = Convertion.Pressure_mTorr_to_mbar(double.Parse(tp));
                                        }

                                        else
                                        {
                                            Detector.Ionchamber.TPpressure = 0.0;
                                        }

                                        Detector.Settings.DetectorMode = Recvmessage[0].Substring(27).TrimEnd(ending).TrimStart(' ');

                                        for (int i = 0; i < 4; i++)
                                        {
                                            if (Detector.ViewModel.MeasurementViewModel.Displays[i].Selection == 1)
                                            {
                                                Detector.ViewModel.MeasurementViewModel.Displays[i].Value = Detector.Ionchamber.Leakrate.ToString("0.00E+0");
                                            }
                                            else if (Detector.ViewModel.MeasurementViewModel.Displays[i].Selection == 2)
                                            {
                                                Detector.ViewModel.MeasurementViewModel.Displays[i].Value = Detector.Ionchamber.TPpressure.ToString("0.00E+0");
                                            }
                                        }

                                        break;
                                    }
                                case ("?AZ<0"):
                                    {
                                        Detector.Settings.AutoZero = Recvmessage[0].IndexOf(" ON ", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?CALOK"):
                                    {
                                        Detector.Calibration.CalibrationStatus = Recvmessage[0].IndexOf(" Yes", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?CALINTOK"):
                                    {
                                        Detector.Calibration.CalibrationStatus = Recvmessage[0].IndexOf(" Yes", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?CPLOCKOUT"):
                                    {
                                        //Lockout = Recvmessage[0].IndexOf(" ON ", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;                                       
                                        break;
                                    }
                                case ("?CURRDATE"):
                                    {
                                        //Settings[6].Value = SearchList("CURRDATE", Recvmessage);
                                        break;
                                    }
                                case ("?DISPLAY"):
                                    {
                                        //Display = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;                                      
                                        break;
                                    }
                                case ("?EMISSION"):
                                    {
                                        Detector.Ionchamber.Emission = SearchList("EMISSION", Recvmessage);
                                        break;
                                    }
                                case ("?EXPONENT"):
                                    {
                                        Detector.Range.Exponent = SearchList("EXPONENT", Recvmessage);
                                        break;
                                    }
                                case ("?EXTLEAK"):
                                    {
                                        Detector.Calibration.ExternalLeak = SearchList("EXTLEAK", Recvmessage);
                                        break;
                                    }
                                case ("?FIL1HOURS"):
                                    {
                                        Detector.Ionchamber.FilHours1 = Recvmessage[0].Substring(11).TrimEnd(ending);
                                        break;
                                    }
                                case ("?FIL2HOURS"):
                                    {
                                        Detector.Ionchamber.FilHours2 = Recvmessage[0].Substring(11).TrimEnd(ending);
                                        break;
                                    }
                                case ("?GAIN"):
                                    {
                                        Detector.Ionchamber.Gain = SearchList("GAIN", Recvmessage);
                                        break;
                                    }
                                case ("?INTERNAL-TYPE"):
                                    {
                                        //Settings[5].Value = Recvmessage[0].Contains("0") ? false : true;
                                        break;
                                    }
                                case ("?INTEXT"):
                                    {
                                        Detector.Calibration.LastCal = Recvmessage[0].Substring(9).TrimEnd(ending);
                                        break;
                                    }
                                case ("?I/O BOARD"):
                                    {
                                        //IOBoard = Recvmessage[0].Contains("0") ? false : true;                                       
                                        break;
                                    }
                                case ("?IONCHAMBER"):
                                    {
                                        Detector.Ionchamber.Voltage = SearchList("IONCHAMBER", Recvmessage);
                                        break;
                                    }
                                case ("?I/O_VER"):
                                    {
                                        //TODO      IOVer = Recvmessage[0].Substring(0).TrimEnd(ending);

                                        break;
                                    }
                                case ("?LANGUAGE"):
                                    {
                                        //int i = Convert.ToInt32(Recvmessage[0].Substring(10).TrimEnd(ending));
                                        //switch (i)
                                        //{
                                        //    case 0: Settings[3].Value = "English"; break;
                                        //    case 1: Settings[3].Value = "French"; break;
                                        //    case 2: Settings[3].Value = "German"; break;
                                        //    case 3: Settings[3].Value = "Korean"; break;
                                        //    case 4: Settings[3].Value = "Spanish"; break;
                                        //    case 5: Settings[3].Value = "Japanese"; break;
                                        //    case 6: Settings[3].Value = "Chinese"; break;
                                        //    default: Settings[3].Value = ""; break;
                                        //}
                                        break;
                                    }
                                case ("?LEAK"):
                                    {
                                        //Detector.Graph.Leak = Convert.ToDouble(SearchList("LEAK", Recvmessage));
                                        break;
                                    }
                                case ("?LKEXPIRE"):
                                    {
                                        Temp = SearchList("LKEXPIRE", Recvmessage).Replace(' ', '/');
                                        string format = "M/d/yyyy";
                                        DateTime.TryParseExact(Temp, format, null, DateTimeStyles.None, out DateTime datum);
                                        Detector.Calibration.InternalExpire = datum.ToString("d/M/yyyy");
                                        break;
                                    }
                                case ("?LEAKTEMP"):
                                    {
                                        Detector.Calibration.InternalTemp = SearchList("LEAKTEMP", Recvmessage);
                                        break;
                                    }
                                /* case ("?LP"):
                                     {
                                         LP = Recvmessage[0].Substring(4).TrimEnd(ending);                                      
                                         break;
                                     }
                                 case ("?LPVR"):
                                     {
                                         LPVR = Recvmessage[0].Substring(6).TrimEnd(ending);                                      
                                         break;
                                     }
                                 case ("?LPVRM"):
                                     {
                                         LPVRM = Recvmessage[0].Substring(7).TrimEnd(ending);                                       
                                         break;
                                     }
                                 case ("?LPVRJG"):
                                     {
                                         LPVRJG = Recvmessage[0].Substring(8).TrimEnd(ending);                                       
                                         break;
                                     }
                                 case ("?LPVRJGC"):
                                     {
                                         LPVRJGC = Recvmessage[0].Substring(9).TrimEnd(ending);                                      
                                         break;
                                     }
                                 case ("?LPVRJGCTbTpV"):
                                     {
                                         LPVRJGCTbTpV = Recvmessage[0].Substring(13).TrimEnd(ending);                                     
                                         break;
                                     }*/
                                case ("?NOCAL-VMAXOUT"):
                                    {
                                        //Nocal = Recvmessage[0].Substring(15).Contains("on") ? true : false;                                      
                                        break;
                                    }
                                case ("?OFFSET"):
                                    {
                                        Detector.Ionchamber.Offset1 = Recvmessage[0].Substring(Recvmessage[0].IndexOfAny(numbers)).TrimEnd(ending);

                                        break;
                                    }
                                case ("?PREHEAT"):
                                    {
                                        //LCB[4].Value = Recvmessage[0].Contains("0") ? false : true;
                                        break;
                                    }
                                case ("?PREHEAT-TIME"):
                                    {
                                        int i = Convert.ToInt32(Recvmessage[0].Substring(14).TrimEnd(ending));
                                        switch (i)
                                        {
                                            case 5:
                                                Detector.Settings.PreaheatSelection = 0;
                                                break;
                                            case 9:
                                                Detector.Settings.PreaheatSelection = 1;
                                                break;
                                            default:
                                                Detector.Settings.PreaheatSelection = 2;
                                                break;
                                        }
                                        break;
                                    }
                                case ("?PRESSURES"):
                                    {
                                        double value = Convert.ToDouble(Recvmessage[1].Substring(19).TrimEnd(ending));
                                        break;
                                    }
                                case ("?PWDONOFF"):
                                    {
                                        // PWDonoff = Recvmessage[0].Contains("on") ? true : false;                                     
                                        break;
                                    }
                                case ("?RANGE"):
                                    {
                                        Detector.Range.RangeValue = Recvmessage[0].Substring(7).TrimEnd(ending);
                                        break;
                                    }
                                case ("?RANGESTOP"):
                                    {
                                        Detector.Range.RangeStop = Recvmessage[0].Substring(11).TrimEnd(ending);
                                        break;
                                    }
                                case ("?1REJECT"):
                                    {
                                        Detector.Reject.Reject1.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?2REJECT"):
                                    {
                                        Detector.Reject.Reject2.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?3REJECT"):
                                    {
                                        Detector.Reject.Reject3.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?4REJECT"):
                                    {
                                        Detector.Reject.Reject4.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?AREJECT"):
                                    {
                                        Detector.Reject.RejectA.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?1REJECTP"):
                                    {
                                        //Rejects[19].Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?2REJECTP"):
                                    {
                                        //Rejects[20].Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?3REJECTP"):
                                    {
                                        //Rejects[21].Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?4REJECTP"):
                                    {
                                        // Rejects[22].Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?>1REJECT"):
                                    {
                                        Detector.Reject.Reject1.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?>2REJECT"):
                                    {
                                        Detector.Reject.Reject2.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?>3REJECT"):
                                    {
                                        Detector.Reject.Reject3.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?>4REJECT"):
                                    {
                                        Detector.Reject.Reject4.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?>AREJECT"):
                                    {
                                        Detector.Reject.RejectA.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?RSONOFF"):
                                    {
                                        Detector.Range.RangestopActive = Recvmessage[0].IndexOf("off") >= 0 ? false : true;
                                        break;
                                    }
                                case ("?SETUP"):
                                    {
                                        Detector.Turbo.TurboSpeed = SearchList("Turbo", Recvmessage);
                                        Detector.Range.Exponent = SearchList("exponent", Recvmessage, 3);
                                        Detector.Range.RangeValue = SearchList("range", Recvmessage);
                                        Detector.Reject.Reject1.Value = SearchList("reject", Recvmessage, 7);
                                        Detector.Reject.Reject2.Value = SearchList("reject", Recvmessage, 7, 8);
                                        Detector.Reject.Reject3.Value = SearchList("reject", Recvmessage, 7, 16);
                                        Detector.Reject.Reject4.Value = SearchList("reject", Recvmessage, 7, 24);
                                        Detector.Reject.RejectA.Value = SearchList("reject", Recvmessage, -1, 32);
                                        Detector.Calibration.InternalLeak = SearchList("stdleak", Recvmessage);
                                        //output
                                        Detector.Ionchamber.FilStatus = Recvmessage[7].Substring(12, 9).TrimStart(' ').TrimEnd(' ');

                                        break;
                                    }
                                case ("?SOFTSTART"):
                                    {
                                        Detector.Turbo.SoftStart = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?SPLITFLOW"):
                                    {
                                        Detector.Calibration.Splitflow = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?STDLEAK"):
                                    {
                                        Detector.Calibration.InternalLeak = Recvmessage[0].Substring(Recvmessage[0].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');
                                        break;
                                    }
                                case ("?STDLK-GAIN"):
                                    {
                                        //LEAK GAIN
                                        break;
                                    }
                                case ("?SYS-GAIN"):
                                    {
                                        //SYS GAIN
                                        break;
                                    }
                                case ("?SYSPWD"):
                                    {
                                        //PSWRD = Recvmessage[0].Substring(Recvmessage[0].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');                                      
                                        break;
                                    }
                                case ("?TC-GAUGE"):
                                    {
                                        //TCGauge = Recvmessage[0].Contains("1") ? true : false;                                       
                                        break;
                                    }
                                case ("?TUNEOK"):
                                    {
                                        //TuneOK 
                                        break;
                                    }
                                case ("?TURBO"):
                                    {
                                        Detector.Turbo.TurboMode = Recvmessage[1].Substring(Recvmessage[1].IndexOf(' ') + 1).TrimEnd(ending).TrimStart(' ');
                                        Detector.Turbo.TurboFault = Recvmessage[2].Substring(Recvmessage[2].IndexOf(' ') + 1).TrimEnd(ending).TrimStart(' ');
                                        Detector.Turbo.TurboSpeed = Recvmessage[3].Substring(Recvmessage[3].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');
                                        Detector.Turbo.TurboTemp = Recvmessage[4].Substring(Recvmessage[4].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');
                                        Detector.Turbo.TurboHours = Recvmessage[5].Substring(Recvmessage[5].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');

                                        break;
                                    }
                                case ("?TURBOHR"):
                                    {
                                        Detector.Turbo.TurboHours = Recvmessage[0].Substring(9).TrimEnd(ending);
                                        break;
                                    }
                                case ("?VALVESTATE"):
                                    {
                                        Detector.Settings.DetectorMode = Recvmessage[0].Substring(12).TrimEnd(ending);
                                        break;
                                    }
                                case ("VER"):
                                    {
                                        //Settings[7].Value = Recvmessage[0].Substring(4).TrimEnd(ending);
                                        break;
                                    }
                                case ("?VOLUMEONOFF"):
                                    {
                                        //Volume = Recvmessage[0].Contains("on") ? true : false;
                                        break;
                                    }
                                case ("WHYNOCAL"):
                                    {
                                        //WHYNOCAL
                                        break;
                                    }
                                case ("WHYNOCAL-INT"):
                                    {
                                        //WHYNOCAL INT

                                        break;
                                    }
                                case ("?0ENABLE"):
                                    {
                                        Detector.Settings.Zero = Recvmessage[0].Contains("on") ? true : false;
                                        break;
                                    }
                                default:
                                    {
                                        Recvmessage.Clear();
                                        break;
                                    }
                            }
                        }
                    }
                    else
                    {
                        Thread.Sleep(10);
                    }
                }
                catch (Exception ex)
                {

                }
            }
        }

        #endregion

        #region Timer elapsed methods

        /// <summary>
        /// Timer for reseting serial communication if response from detector is not received
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RecvTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            ResetSerial();
        }

        /// <summary>
        /// Timer for equiring Leakrate and testport pressure
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LPVTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Detector.SendToDetector("?LPV");
        }

        /// <summary>
        /// Timer for getting data according to actually selected tab in tabcontrol
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GetDataTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (SendQueue.Count < 10)
            {


                if (Initialization)
                {
                    Detector.SendToDetector("SERVICE1");
                    Detector.SendToDetector("SERVICE2");
                    Detector.SendToDetector("?TURBO");
                    Detector.SendToDetector("?RANGESTOP");
                    Detector.SendToDetector("?FIL1HOURS");
                    Detector.SendToDetector("?FIL2HOURS");
                    Detector.SendToDetector("?SETUP");
                    Detector.SendToDetector("?CALOK");
                    Detector.SendToDetector("?INTEXT");

                    Initialization = false;
                }
                else
                {
                    if (Detector.ViewModel.MeasurementViewModel.TabcontrolIndex == 0)
                    {
                        if (SettingViewModel.DetectorIndex == 0)
                        {
                            Detector.SendToDetector("?CALINTOK", false);
                        }
                        else
                        {
                            Detector.SendToDetector("?CALOK", false);
                        }
                        Detector.SendToDetector("?SETUP", false);
                        Detector.SendToDetector("?>1REJECT", false);
                        Detector.SendToDetector("?>2REJECT", false);
                        Detector.SendToDetector("?>3REJECT", false);
                        Detector.SendToDetector("?>4REJECT", false);
                        Detector.SendToDetector("?>AREJECT", false);

                    }
                    else if (Detector.ViewModel.MeasurementViewModel.TabcontrolIndex == 1)
                    {
                        Detector.SendToDetector("?TURBO", false);
                        Detector.SendToDetector("?SETUP", false);
                        Detector.SendToDetector("?ALL", false);

                    }
                    else if (Detector.ViewModel.MeasurementViewModel.TabcontrolIndex == 4)
                    {
                        foreach (Parameter par in Detector.ViewModel.ParameterViewModel.Parameters)
                        {
                            if (!string.IsNullOrEmpty(par.EnquiryName))
                                Detector.SendToDetector(par.EnquiryName, false);
                        }
                    }
                }
            }

        }
        #endregion

        #region Helper methods for processing serial data

        /// <summary>
        /// Method for searching list for specific string - in found string searches for any number
        /// </summary>
        /// <param name="search"></param>
        /// <param name="list"></param>
        /// <param name="length"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        private string SearchList(string search, List<string> list, int length = -1, int offset = 0)
        {
            int index = list.FindIndex(r => r.Contains(search));
            if (index != -1)
            {
                string data;
                if (length == -1)
                {
                    if (offset == 0)
                        data = list[index].Substring(list[index].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');
                    else
                        data = list[index].Substring(list[index].IndexOfAny(numbers) + offset).TrimEnd(ending).TrimStart(' ');
                }
                else
                {
                    if (offset == 0)
                        data = list[index].Substring(list[index].IndexOfAny(numbers), length).TrimEnd(ending).TrimStart(' ');
                    else
                        data = list[index].Substring(list[index].IndexOfAny(numbers) + offset, length).TrimEnd(ending).TrimStart(' ');
                }
                return data;
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Method for getting reject state
        /// </summary>
        /// <param name="rejectstring"></param>
        /// <param name="On"> Gets if reject is On or Off</param>
        /// <param name="High"> Gets if reject is set for higher value or lower value </param>
        /// <param name="Leak"> Gets if reject is set for leakrate or pressure value </param>
        private void SearchReject(string rejectstring, out bool On, out bool High, out bool Leak)
        {
            On = rejectstring.IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
            High = rejectstring.IndexOf("HIGH", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
            Leak = rejectstring.IndexOf("LR", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
        }

        /// <summary>
        /// Method for searching list for specific string - returns true if found
        /// </summary>
        /// <param name="search"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        private bool SearchListBool(string search, List<string> list)
        {
            int index = list.FindIndex(r => r.Contains(search));
            if (index != -1)
            {
                return Recvmessage[index].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0;
            }
            return false;
        }
        #endregion
    }

}


