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

namespace QTInterface
{
    public class TCS
    {
        private string m_port = "";
        private int m_baudrate = 9600;
        private SerialPort m_serial = null;
        public static string power = "";           //电源灯端口
        public static string stust = "";           //状态灯端口
        public static string left = "";           //电源灯端口
        public static string right = "";           //状态灯端口
        private object loc=new object();
        Adb_Common adb = new Adb_Common();
        SerialPortMangment port_man = new SerialPortMangment();

        public TCS(string port, int baudrate=9600)
        {
            this.m_port = port;
            this.m_baudrate = baudrate;
        }

        /// <summary>
        /// 打开端口
        /// </summary>
        /// <returns></returns>
        public bool OpenPort()
        {
            if (m_serial == null)
            {
                m_serial = new SerialPort(m_port, m_baudrate, Parity.None, 8, StopBits.One);
                m_serial.ReadTimeout = 9000;
            }
            try
              {
                 if (m_serial.IsOpen == false)
                {
                    m_serial.Open();
                }
                return m_serial.IsOpen;
            }
            catch(Exception ex)
            {
                /* 验证逻辑： 每次加载一次端口，重连一次验证禁用弃用端口是否可以避免端口卡死的情况 */
                this.Close();
                //1.查找COM口
                port_man.GetDevices(m_serial.PortName);
                //2.禁用端口
                string msg_1 = port_man.DeviceDisable();
                FileWriter.WriteLog(m_serial.PortName + " DeviceDisable():" + msg_1);
                //3.启用端口
                string msg_2 = port_man.DeviceEnable();
                FileWriter.WriteLog(m_serial.PortName + " DeviceEnable():" + msg_2);
                m_serial = null;

                //将异常写入文件
                FileWriter.WriteLog("rgb port open Exception:" + ex.Message);
                if (m_serial == null)
                {
                    m_serial = new SerialPort(m_port, m_baudrate, Parity.None, 8, StopBits.One);
                    m_serial.ReadTimeout = 9000;
                }
                try
                {
                    if (m_serial.IsOpen == false)
                    {
                        m_serial.Open();
                    }
                    return m_serial.IsOpen;
                }
                catch (Exception e)
                {
                    m_serial = null;
                    //将异常写入文件
                    FileWriter.WriteLog("rgb port open Exception:" + ex.Message);
                    return false;
                }
            }
        }

        /// <summary>
        /// 读r,g,b数据
        /// </summary>
        /// <param name="timeout">超时时间，单位秒，默认10</param>
        /// <returns>读到返回[r,g,b]/未读到null</returns>
        public int[] ReadRGB(int timeout=5) 
        {
            lock (loc)
            {
                string cmd = "get RGB value\r\n";
                string rev_cmd = "";
                if (OpenPort())
                {
                    int r = -1, g = -1, b = -1;
                    DateTime end = DateTime.Now.AddSeconds(timeout);
                    while (DateTime.Now <= end)
                    {
                        for (int i = 0; i < 3; i++)
                        {
                            try
                            {
                                this.m_serial.ReadExisting();
                                this.m_serial.WriteLine(cmd);
                                FileWriter.WriteLog("rgb data send:" + cmd);
                                if (this.m_serial.IsOpen)
                                {
                                    rev_cmd = this.m_serial.ReadLine();
                                    //NAK時再試一次
                                    if (rev_cmd.ToUpper() == "NAK")
                                    {
                                        Thread.Sleep(10);
                                        this.m_serial.WriteLine(cmd);
                                        FileWriter.WriteLog("rgb data send:" + cmd);
                                        if (this.m_serial.IsOpen)
                                        {
                                            rev_cmd = this.m_serial.ReadLine();
                                        }
                                    }
                                }
                                else
                                {
                                    FileWriter.WriteLog("m_serial is closed");
                                    return null;
                                }
                            }
                            catch (Exception e)
                            {
                                OpenPort();
                                FileWriter.WriteLog("ReadLine ex ==" + e.ToString());
                                continue;
                            }
                            FileWriter.WriteLog("rgb data rev:" + cmd);
                            if (rev_cmd.ToUpper() == "NAK" || rev_cmd.Length == 0)
                            {
                                Thread.Sleep(500);
                                //将异常写入文件
                                FileWriter.WriteLog("rgb read value:" + rev_cmd.ToUpper());
                                /* 验证逻辑： 出现返回值为空的情况，重新启用端口 */
                                this.Close();
                                //1.查找COM口
                                port_man.GetDevices(m_serial.PortName);
                                //2.禁用端口
                                string msg_1 = port_man.DeviceDisable();
                                FileWriter.WriteLog(m_serial.PortName + " DeviceDisable():" + msg_1);
                                //3.启用端口
                                string msg_2 = port_man.DeviceEnable();
                                FileWriter.WriteLog(m_serial.PortName + " DeviceEnable():" + msg_2);
                                m_serial = null;

                               
                                if (m_serial == null)
                                {
                                    m_serial = new SerialPort(m_port, m_baudrate, Parity.None, 8, StopBits.One);
                                    m_serial.ReadTimeout = 9000;
                                }
                                try
                                {
                                    if (m_serial.IsOpen == false)
                                    {
                                        m_serial.Open();
                                    }
                                }
                                catch (Exception e)
                                {
                                    m_serial = null;
                                    //将异常写入文件
                                    FileWriter.WriteLog("rgb port open Exception:" + e.Message);
                                }
                                Thread.Sleep(500);
                            }
                            else
                            {
                                //R=69,G=110,B=101\r
                                
                                var sps = rev_cmd.Split(new string[] { ",", "\r" }, StringSplitOptions.RemoveEmptyEntries);
                                foreach (string data in sps)
                                {
                                    var datas = data.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                                    if (data.ToLower().Contains("r"))
                                    {
                                        if (datas.Length >= 2)
                                        {
                                            r = Convert.ToInt32(datas[1]);
                                        }
                                    }
                                    else if (data.ToLower().Contains("g"))
                                    {
                                        if (datas.Length >= 2)
                                        {
                                            g = Convert.ToInt32(datas[1]);
                                        }
                                    }
                                    else if (data.ToLower().Contains("b"))
                                    {
                                        if (datas.Length >= 2)
                                        {
                                            b = Convert.ToInt32(datas[1]);
                                        }
                                    }
                                }
                                FileWriter.WriteLog(string.Format("r={0}, g={1},b={2},COM={3}", r, g, b,m_port));
                            }
                            return new int[] { r, g, b };
                        }
                        
                    }
                    FileWriter.WriteLog(string.Format("ReadRGB timeout"));
                    Thread.Sleep(1);
                    return null;
                }
                return null;
            }
        }
        
        /// <summary>
        /// 关闭端口
        /// </summary>
        public void Close()
        {
            try
            {
                if (m_serial != null)
                {
                    m_serial.Close();
                    m_serial.Dispose();
                }
            }
            catch(Exception ex)
            {
                FileWriter.WriteLog("Close Exception:" + ex.Message);
            }
        }

        /// <summary>
        /// 读r,g,b数据
        /// </summary>
        /// <returns>[r,g,b]</returns>
        public double ReadLux(int timeout = 10)
        {
            lock (loc)
            {
                try
                {
                    string cmd = "get lux value\r\n";
                    if (OpenPort())
                    {
                        DateTime end = DateTime.Now.AddSeconds(timeout);
                        while (DateTime.Now <= end)
                        {
                            m_serial.DiscardInBuffer();
                            m_serial.DiscardOutBuffer();
                            this.m_serial.WriteLine(cmd);
                            //Thread                  
                            string rev_cmd = this.m_serial.ReadLine();
                            if (rev_cmd.ToUpper() == "NAK" || rev_cmd.Length == 0)
                            {
                                Thread.Sleep(1000);   //延迟1秒
                            }
                            else
                            {
                                var datas = rev_cmd.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                                if (datas.Length >= 2)
                                {
                                    return Convert.ToDouble(datas[1]);
                                }
                            }
                        }
                        FileWriter.WriteLog("ReadLux timeout");
                        return -1;
                    }
                }
                catch ( Exception ex)
                {
                    FileWriter.WriteLog("ReadLux Exception:" + ex.Message);
                    return -1;
                }
                return -1;
            }
        }

        /// <summary>
        /// 设置r,g,b数据
        /// </summary>
        /// <returns>[r,g,b]</returns>
        public bool SetRGB(string value,int timeout = 10)
        {
            lock (loc)
            {
                string cmd = "set TCS34725 gain " + value + "\r\n";
                try
                {
                    //Thread.Sleep(100);   //延迟0.1秒
                    DateTime end = DateTime.Now.AddSeconds(timeout);
                    while (DateTime.Now <= end)
                    {

                        this.m_serial.ReadExisting();
                        //Thread.Sleep(80);
                        this.m_serial.WriteLine(cmd);
                        //Thread                  
                        string rev_cmd = this.m_serial.ReadLine();
                        if (rev_cmd.ToUpper() == "NAK" || rev_cmd.Length == 0)
                        {
                            //Thread.Sleep(100);   //延迟1秒
                        }
                        else
                        {
                            var datas = rev_cmd.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                            if (datas[0] == "OK\r")
                            {
                                FileWriter.WriteLog("Set RGB ok! ");
                                return true;
                            }
                        }
                        Thread.Sleep(100);   //延迟
                    }
                    FileWriter.WriteLog("Set RGB timeout !");
                }
                catch (Exception e)
                {
                    FileWriter.WriteLog("Set RGB fail " + e.ToString());
                    return false;
                }
                return false;
            } 
        }
    }
}
