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

namespace VSview
{
    public class DetectorCommunication : BaseViewModel
    {

        #region Public members

        //List of avaliable ports
        public List<string> portNames = new List<string>();

        //Send queue to the detector 
        public static LinkedList<Message> SendQueue;

        #endregion;

        #region Private members

        //reference to main viewmodel
        private MainViewModel ViewModel;

        //serial port
        private static SerialPort port;

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

        //Thread managing        
        private bool _ComThreadWorking = true;

        //Serial communication thread
        private Thread SerialThread;

        //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 DispatcherTimer GetDataTimer;

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

        //Timer for cyclic leakrate and test port pressure enquiring
        private DispatcherTimer LPVTimer;

        //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 Constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        public DetectorCommunication() { }

        /// <summary>
        /// Main constructor for serial port 
        /// </summary>
        public DetectorCommunication(MainViewModel viewModel)
        {
            //create reference for VM_Serial binding class
            ViewModel = viewModel;
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Method for connecting and disconecting using selected port
        /// </summary>
        public void OpenCloseSerial()
        {
            new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;

                if (!port.IsOpen)
                {
                    ViewModel.WriteToLog("Connecting...\n");
                    if (ViewModel.Detector.Settings.SerialPortSelection >= 0)
                    {
                        //set portname acording to selection in UI
                        port.PortName = ViewModel.Detector.Settings.SerialPorts[ViewModel.Detector.Settings.SerialPortSelection];

                        //Test port for detector pressence
                        if (TestPort(port, out string DetectorType) && port.IsOpen)
                        {
                            //Notify succesfull connection
                            ViewModel.Detector.Settings.IsConnected = true;
                            //Aquire connected detector type
                            ViewModel.Detector.Settings.DetectorSelection = ViewModel.Detector.Settings.DetectorTypes.IndexOf(DetectorType);
                            //Make note in log about connecting
                            ViewModel.WriteToLog(port.PortName + " is connected\n" + DetectorType + " detector found\n");
                            //Start serial communication with detector
                            StartSerialCommunication();
                        }
                        else if (!port.IsOpen)
                        {
                            StopSerialCommunication();
                            ViewModel.WriteToLog("Port " + port.PortName + " could not be connected, please check connetion\n");
                        }
                    }
                    else
                    {
                        //No port is selected in UI
                        ViewModel.WriteToLog("No COM port is selected");
                    }

                }
                else
                {
                    //Make note in log about closing of serial port
                    ViewModel.WriteToLog("Closing port " + port.PortName + " \n");
                    //Close port
                    ClosePort(port);
                }
            }).Start();
        }

        /// <summary>
        /// Method for scanning new serial ports
        /// </summary>
        public void ScanForPorts()
        {
            //Clear list of ports
            if (ViewModel.Detector.Settings.SerialPorts.Count > 0)
                ViewModel.Detector.Settings.SerialPorts.Clear();

            //Search for all serial ports
            foreach (string port in SerialPort.GetPortNames())
            {
                ViewModel.Detector.Settings.SerialPorts.Add(port);
            }
        }

        /// <summary>
        /// Method for closing serial port - called from another thread
        /// </summary>
        /// <param name="Port">Port to be closed</param>
        public void ClosePort(SerialPort Port)
        {
            try
            {
                if (Port.IsOpen)
                {
                    StopSerialCommunication();

                    ClearSerialCom();

                    Port.Close();
                }
                if (!Port.IsOpen)
                {
                    ViewModel.Detector.Settings.IsConnected = false;
                }
            }
            catch (Exception ex)
            {

            }

        }

        /// <summary>
        /// Method for autodetection of used port
        /// </summary>
        public void Autodetection()
        {
            if (!port.IsOpen)
            {
                if (portNames.Count > 0)
                {
                    ViewModel.WriteToLog("Connecting...\n");
                    new Thread(() =>
                    {
                        Thread.CurrentThread.IsBackground = true;

                        //Try each awailiable port
                        foreach (string portName in portNames)
                        {
                            //assign portname
                            port.PortName = portName;

                            //Test port for detector
                            if (TestPort(port, out string DetectorType) && port.IsOpen)
                            {
                                //Notify succesfull connection
                                ViewModel.Detector.Settings.IsConnected = true;
                                //Aquire connected detector type
                                ViewModel.Detector.Settings.DetectorSelection = ViewModel.Detector.Settings.DetectorTypes.IndexOf(DetectorType);
                                //Make note in log about connecting
                                ViewModel.WriteToLog(port.PortName + " is connected\n" + DetectorType + " detector found\n");
                                //Start serial communication with detector
                                StartSerialCommunication();
                            }
                            else if (!port.IsOpen)
                            {
                                StopSerialCommunication();
                                ViewModel.WriteToLog("Port " + port.PortName + " could not be connected, please check connetion\n");
                            }
                        }

                    }).Start();
                }
                else
                {
                    ViewModel.WriteToLog("No port for connection is available\n");
                    ViewModel.WriteToLog("Scanning for available ports..\n");
                    ScanForPorts();
                }
            }
            else
            {
                ViewModel.WriteToLog(port.PortName + " is connected\n");
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Method for initialization of serial port
        /// </summary>
        private void InitializeSerial()
        {
            //Initialize queues
            SendQueue = new LinkedList<Message>();
            RecvQueue = new LinkedList<List<string>>();

            //Initialize serial port
            port = new SerialPort                   //create new serial port
            {
                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  
            };

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

        /// <summary>
        /// Method for creating timers
        /// </summary>
        private void InitializeTimers()
        {
            //timer for checking if message was received in time
            RecvTimeout = new DispatcherTimer();
            RecvTimeout.Interval = TimeSpan.FromSeconds(3.0);
            RecvTimeout.Tick += RecvTimeout_Tick;

            //timer for cyclic data requesting
            GetDataTimer = new DispatcherTimer();
            GetDataTimer.Interval = TimeSpan.FromSeconds(5.0);
            GetDataTimer.Tick += GetDataTimer_Tick;
            GetDataTimer.Start();

            //Timer for leak rate data request
            LPVTimer = new DispatcherTimer();
            LPVTimer.Interval = TimeSpan.FromMilliseconds(500.0);
            LPVTimer.Tick += LPVTimer_Tick;
            LPVTimer.Start();
        }

        /// <summary>
        /// Method for sending data to the serial port
        /// </summary>
        private void SerialReadWrite()
        {
            while (_ComThreadWorking)
            {
                try
                {
                    if (ViewModel.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();

                            //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();

                            // 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)
                                ViewModel.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)
                {
                    ClearSerialCom();
                }
            }
        }

        /// <summary>
        /// Clears serial communication if error occurs
        /// </summary>
        private void ClearSerialCom()
        {
            //Clear send queue
            if (SendQueue.Count > 0)
                SendQueue.Clear();

            //Discard In buffer
            if (port.BytesToRead > 0)
                port.DiscardInBuffer();

            //Discard Out buffer
            if (port.BytesToWrite > 0)
                port.DiscardOutBuffer();

            responseRecv = true;
            RecvTimeout.Stop();
        }

        /// <summary>
        /// Method starts timers and communication thread
        /// </summary>
        private void StartSerialCommunication()
        {
            InitializeSerial();

            InitializeTimers();
        }

        /// <summary>
        /// Method stops timers 
        /// </summary>
        private void StopSerialCommunication()
        {
            RecvTimeout.Stop();
            RecvTimeout = null;

            GetDataTimer.Stop();
            GetDataTimer = null;

            LPVTimer.Stop();
            LPVTimer = null;

            SerialThread.Abort();
        }

        /// <summary>
        /// Method for testing port communication - called from another thread
        /// </summary>
        /// <param name="Port">port to be tested</param>
        /// <returns></returns>
        private bool TestPort(SerialPort Port, out string DetectorType)
        {
            try
            {
                Port.Open();
                Port.Write("?CALINTOK\r");
                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)
            {
                ClosePort(Port);
                DetectorType = string.Empty;
                return false;
            }
        }

        /// <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 (true)
            {
                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"):
                                    {

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

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

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

                                        SearchReject(Recvmessage[rejectindex + 1], ViewModel.Detector.Reject.Reject1.State, out bool High, out bool Low, out bool Leak, out bool Press);
                                        ViewModel.Detector.Reject.Reject1.State = State;
                                        ViewModel.Detector.Reject.Reject1.IsHigh = High;
                                        ViewModel.Detector.Reject.Reject1.IsLow = Low;
                                        ViewModel.Detector.Reject.Reject1.IsLeak = Leak;
                                        ViewModel.Detector.Reject.Reject1.IsPressure = Press;

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

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

                                        SearchReject(Recvmessage[rejectindex], out bool State, out bool High, out bool Low, out bool Leak, out bool Press);
                                        ViewModel.Detector.Reject.Reject1.State = State;
                                        ViewModel.Detector.Reject.Reject1.IsHigh = High;
                                        ViewModel.Detector.Reject.Reject1.IsLow = Low;
                                        ViewModel.Detector.Reject.Reject1.IsLeak = Leak;
                                        ViewModel.Detector.Reject.Reject1.IsPressure = Press;
                                        Temp = SearchList("Leak Expiration", Recvmessage).Replace(' ', '/');
                                        string format = "M/d/yyyy";
                                        DateTime.TryParseExact(Temp, format, null, DateTimeStyles.None, out DateTime datum);
                                        ViewModel.Detector.Calibration.InternalExpire = datum.ToString("d/M/yyyy");

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

                                        if (ViewModel.Detector.Settings.DetectorSelection == 0)
                                        {
                                            Temp = SearchList("OFFSET", Recvmessage).TrimStart(' ');
                                            ViewModel.Detector.Ionchamber.Offset1 = Temp.Substring(0, Temp.IndexOf(' '));
                                            Temp = SearchList("GAIN", Recvmessage).TrimStart(' ');
                                            ViewModel.Detector.Ionchamber.Gain = Temp.Substring(0, Temp.IndexOf(' '));
                                        }
                                        else
                                        {
                                            int RecvmessageIndex = Recvmessage.FindIndex(r => r.Contains("OFFSET"));
                                            int index1 = Recvmessage[RecvmessageIndex].IndexOfAny(numbers);
                                            int index2 = Recvmessage[RecvmessageIndex].Substring(index1).IndexOf(' ');
                                            ViewModel.Detector.Ionchamber.Offset1 = Recvmessage[RecvmessageIndex].Substring(index1, index2);
                                            ViewModel.Detector.Ionchamber.Offset2 = Recvmessage[RecvmessageIndex].Substring(index1 + index2 + 1).TrimEnd(ending);
                                            ViewModel.Detector.Ionchamber.Gain = SearchList("GAIN", Recvmessage);
                                        }

                                        break;
                                    }
                                case ("?LPV"):
                                    {
                                        //ViewModel.Detector.Graph.Leak = double.Parse(Recvmessage[0].Substring(5, 8).TrimEnd(ending));

                                        //ViewModel.Detector.Graph.Pressure = ViewModel.Detector.Convertion.Pressure_mTorr_to_mbar(Convert.ToDouble(Recvmessage[0].Substring(Recvmessage[0].IndexOf(" ", 6) + 1, 6).TrimStart('0')));

                                        break;
                                    }
                                case ("?AZ<0"):
                                    {
                                        ViewModel.Detector.Settings.AutoZero = Recvmessage[0].IndexOf(" ON ", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?CALOK"):
                                    {
                                        ViewModel.Detector.Calibration.CalibrationStatus = Recvmessage[0].IndexOf(" Yes", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?CALINTOK"):
                                    {
                                        ViewModel.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"):
                                    {
                                        ViewModel.Detector.Ionchamber.Emission = SearchList("EMISSION", Recvmessage);
                                        break;
                                    }
                                case ("?EXPONENT"):
                                    {
                                        ViewModel.Detector.Range.Exponent = SearchList("EXPONENT", Recvmessage);
                                        break;
                                    }
                                case ("?EXTLEAK"):
                                    {
                                        ViewModel.Detector.Calibration.ExternalLeak = SearchList("EXTLEAK", Recvmessage);
                                        break;
                                    }
                                case ("?FIL1HOURS"):
                                    {
                                        ViewModel.Detector.Ionchamber.FilHours1 = Recvmessage[0].Substring(11).TrimEnd(ending);
                                        break;
                                    }
                                case ("?FIL2HOURS"):
                                    {
                                        ViewModel.Detector.Ionchamber.FilHours2 = Recvmessage[0].Substring(11).TrimEnd(ending);
                                        break;
                                    }
                                case ("?GAIN"):
                                    {
                                        ViewModel.Detector.Ionchamber.Gain = SearchList("GAIN", Recvmessage);
                                        break;
                                    }
                                case ("?INTERNAL-TYPE"):
                                    {
                                        //Settings[5].Value = Recvmessage[0].Contains("0") ? false : true;
                                        break;
                                    }
                                case ("?INTEXT"):
                                    {
                                        ViewModel.Detector.Calibration.LastCal = Recvmessage[0].Substring(9).TrimEnd(ending);
                                        break;
                                    }
                                case ("?I/O BOARD"):
                                    {
                                        //IOBoard = Recvmessage[0].Contains("0") ? false : true;                                       
                                        break;
                                    }
                                case ("?IONCHAMBER"):
                                    {
                                        ViewModel.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"):
                                    {
                                        //ViewModel.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);
                                        ViewModel.Detector.Calibration.InternalExpire = datum.ToString("d/M/yyyy");
                                        break;
                                    }
                                case ("?LEAKTEMP"):
                                    {
                                        ViewModel.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"):
                                    {

                                        if (ViewModel.Detector.Settings.DetectorSelection == 0)
                                        {
                                            ViewModel.Detector.Ionchamber.Offset1 = Recvmessage[0].Substring(Recvmessage[0].IndexOfAny(numbers)).TrimEnd(ending);
                                        }
                                        else
                                        {
                                            int index1 = Recvmessage[0].IndexOfAny(numbers);
                                            int index2 = Recvmessage[0].Substring(index1).IndexOf(' ');
                                            ViewModel.Detector.Ionchamber.Offset1 = Recvmessage[0].Substring(index1, index2);
                                            ViewModel.Detector.Ionchamber.Offset2 = Recvmessage[0].Substring(index1 + index2 + 1).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:
                                                ViewModel.Detector.Settings.PreaheatSelection = 0;
                                                break;
                                            case 9:
                                                ViewModel.Detector.Settings.PreaheatSelection = 1;
                                                break;
                                            default:
                                                ViewModel.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"):
                                    {
                                        ViewModel.Detector.Range.RangeValue = Recvmessage[0].Substring(7).TrimEnd(ending);
                                        break;
                                    }
                                case ("?RANGESTOP"):
                                    {
                                        ViewModel.Detector.Range.RangeStop = Recvmessage[0].Substring(11).TrimEnd(ending);
                                        break;
                                    }
                                case ("?1REJECT"):
                                    {
                                        ViewModel.Detector.Reject.Reject1.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?2REJECT"):
                                    {
                                        ViewModel.Detector.Reject.Reject2.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?3REJECT"):
                                    {
                                        ViewModel.Detector.Reject.Reject3.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?4REJECT"):
                                    {
                                        ViewModel.Detector.Reject.Reject4.Value = Recvmessage[0].Substring(Recvmessage[0].IndexOf(' ') + 1).TrimEnd(ending);
                                        break;
                                    }
                                case ("?AREJECT"):
                                    {
                                        ViewModel.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"):
                                    {
                                        ViewModel.Detector.Reject.Reject1.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?>2REJECT"):
                                    {
                                        ViewModel.Detector.Reject.Reject2.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?>3REJECT"):
                                    {
                                        ViewModel.Detector.Reject.Reject3.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?>4REJECT"):
                                    {
                                        ViewModel.Detector.Reject.Reject4.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?>AREJECT"):
                                    {
                                        ViewModel.Detector.Reject.RejectA.IsActive = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?RSONOFF"):
                                    {
                                        ViewModel.Detector.Range.RangestopActive = Recvmessage[0].IndexOf("off") >= 0 ? false : true;
                                        break;
                                    }
                                case ("?SETUP"):
                                    {
                                        ViewModel.Detector.Turbo.TurboSpeed = SearchList("Turbo", Recvmessage);
                                        ViewModel.Detector.Range.Exponent = SearchList("exponent", Recvmessage, 3);
                                        ViewModel.Detector.Range.RangeValue = SearchList("range", Recvmessage);
                                        ViewModel.Detector.Reject.Reject1.Value = SearchList("reject", Recvmessage, 7);
                                        ViewModel.Detector.Reject.Reject2.Value = SearchList("reject", Recvmessage, 7, 8);
                                        ViewModel.Detector.Reject.Reject3.Value = SearchList("reject", Recvmessage, 7, 16);
                                        ViewModel.Detector.Reject.Reject4.Value = SearchList("reject", Recvmessage, 7, 24);
                                        ViewModel.Detector.Reject.RejectA.Value = SearchList("reject", Recvmessage, -1, 32);
                                        ViewModel.Detector.Calibration.InternalLeak = SearchList("stdleak", Recvmessage);
                                        //output
                                        ViewModel.Detector.Ionchamber.FilStatus = Recvmessage[7].Substring(12, 9).TrimStart(' ').TrimEnd(' ');

                                        break;
                                    }
                                case ("?SOFTSTART"):
                                    {
                                        ViewModel.Detector.Turbo.SoftStart = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?SPLITFLOW"):
                                    {
                                        ViewModel.Detector.Calibration.Splitflow = Recvmessage[0].IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0 ? true : false;
                                        break;
                                    }
                                case ("?STDLEAK"):
                                    {
                                        ViewModel.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"):
                                    {
                                        ViewModel.Detector.Turbo.TurboMode = Recvmessage[1].Substring(Recvmessage[1].IndexOf(' ') + 1).TrimEnd(ending).TrimStart(' ');
                                        ViewModel.Detector.Turbo.TurboFault = Recvmessage[2].Substring(Recvmessage[2].IndexOf(' ') + 1).TrimEnd(ending).TrimStart(' ');
                                        ViewModel.Detector.Turbo.TurboSpeed = Recvmessage[3].Substring(Recvmessage[3].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');
                                        ViewModel.Detector.Turbo.TurboSpeed = Recvmessage[4].Substring(Recvmessage[4].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');
                                        ViewModel.Detector.Turbo.TurboHours = Recvmessage[5].Substring(Recvmessage[5].IndexOfAny(numbers)).TrimEnd(ending).TrimStart(' ');

                                        break;
                                    }
                                case ("?TURBOHR"):
                                    {
                                        ViewModel.Detector.Turbo.TurboHours = Recvmessage[0].Substring(9).TrimEnd(ending);
                                        break;
                                    }
                                case ("?VALVESTATE"):
                                    {
                                        // Settings[0].Value = 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"):
                                    {
                                        ViewModel.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

        private void RecvTimeout_Tick(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        private void LPVTimer_Tick(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        private void GetDataTimer_Tick(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Helper methods for processing serial data
        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;
            }
        }

        private void SearchReject(string rejectstring, out bool state, out bool High, out bool Low, out bool Leak, out bool Press)
        {
            if (rejectstring.IndexOf("ON", StringComparison.OrdinalIgnoreCase) >= 0)
                state = true;            
            else            
              state = false;            

            if (rejectstring.IndexOf("HIGH", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                High = true;
                Low = false;
            }
            else
            {
                High = false;
                Low = true;
            }

            if (rejectstring.IndexOf("LR", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                Leak = true;
                Press = false;
            }
            else
            {
                Leak = false;
                Press = true;
            }
        }

        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
    }

}


