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

namespace IOBoardControl
{
    public class IOBoard
    {
        public SerialPort rs232 = null;
        string RecvString = "";
        private object objLock = new object();
        public String ReadValue = String.Empty;
        private static object lockObj = new object();
        private static object loc = new object();
        Adb_Common adb = new Adb_Common();
        private string Port="";

        public IOBoard(string COM)
            : this(COM, 115200, Parity.None, 8, StopBits.One)
        { }

        public IOBoard(string port,
            int baudRate, Parity parity, int dataBits, StopBits stopBits)
        {
            try
            {
                rs232 = new SerialPort(port, baudRate, parity, dataBits, stopBits);
                rs232.Handshake = Handshake.None;
                rs232.ReceivedBytesThreshold = 1;
                rs232.DtrEnable = true;
                rs232.RtsEnable = true;
                rs232.NewLine = "\r\n";
                rs232.ReadTimeout = 5000;
                rs232.WriteTimeout = 5000;
                Port = port;
                //rs232.DataReceived += rs232_DataReceived;

            }
            catch
            {
            }
        }

        # region 通讯处理
        public int Str2HexOut(string str)
        {
            if (str == "")
            {
                return 0x00FF;
            }
            str = str.Substring(str.IndexOf("0xFFF") + 2, 4);
            char[] c = str.ToCharArray();
            int[] b = new int[4];
            for (int i = 0; i < 4; i++)
            {
                b[i] = HexChar(c[i]);
            }
            int a = b[0] * 16 * 16 * 16 + b[1] * 16 * 16 + b[2] * 16 + b[3];
            return a;

        }

        public bool GetOUT(int num)
        {
            lock (loc)
            {
                string s = "";
                for (int i = 0; i < 5; i++)
                {
                    rs232.Write("ReadDO\r\n");
                    rs232.DiscardOutBuffer();
                    Thread.Sleep(100);
                    s = this.Read().Trim();
                    if (s != "")
                    {
                        break;
                    }
                }

                int a = Str2HexOut(s);
                a = a & 0x00ff;
                a = a >> num - 1;
                return (a & 1) == 0;
            }
        }
        public bool GetIN(int num,int try_count = 6)
        {
            lock (loc)
            {
                if (rs232 == null)
                {
                    return false;
                }
                this.rs232.DiscardInBuffer();
                this.rs232.DiscardOutBuffer();

                while (try_count >= 1)
                {
                    try
                    {
                        rs232.Write("ReadDI\r\n");
                        rs232.DiscardOutBuffer();
                        Thread.Sleep(30);
                        string s = "";
                        //s = this.Read().Trim();
                        s = rs232.ReadTo(">");
                        var sps = s.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                        if (sps.Length >= 3 && sps[2] == "OK")
                        {
                            string hex = sps[1];
                            int data = Convert.ToInt32(hex, 16);
                            int st = data >> (num - 1) & 0x01;
                            if (st == 0)
                            {
                                return st == 0;
                            }
                        }
                        try_count -= 1;
                    }
                    catch (Exception ex)
                    {
                        try_count -= 1;
                        FileWriter.WriteLog("GetIN ReadDI " + "Exception：" + ex.Message);//写入到LOG文件
                    }
                    Thread.Sleep(5);
                }
                return false;
            }
        }

        /// <summary>
        /// 检测端口是否正确
        /// </summary>
        /// <returns></returns>
        public bool CheckSerial()
        {
            this.rs232.DiscardInBuffer();
            this.rs232.DiscardOutBuffer();
            try
            {
                rs232.Write("ReadDI\r\n");
                rs232.DiscardOutBuffer();
                Thread.Sleep(50);
                string s = "";
                s = this.Read().Trim();
                return string.IsNullOrEmpty(s) == false;
            }
            catch (Exception ex)
            {
                FileWriter.WriteLog("CheckSerial ReadDI " + "Exception：" + ex.Message);//写入到LOG文件
                return false;
            }
        }
        public int Str2HexEM(string str)
        {
            if (str == "")
            {
                return 0x00000;
            }
            str = str.Substring(str.IndexOf("0xFFF") + 2, 5);
            char[] c = str.ToCharArray();
            int[] b = new int[5];
            for (int i = 0; i < 5; i++)
            {
                b[i] = HexChar(c[i]);
            }
            int a = b[0] * 16 * 16 * 16 * 16 + b[1] * 16 * 16 * 16 + b[2] * 16 * 16 + b[3] * 16 + b[4];
            return a;
        }
        public int HexChar(char c)
        {
            int i = 0;
            if ((c >= '0') && (c <= '9'))
            {
                i = Int32.Parse(c.ToString());
                return i;
            }
            else
            {
                i = c - 'A' + 10;
                return i;
            }

        }
        public int Str2Hex(string str)
        {
            int a = 0;
            try
            {
                if (str == "")
                {
                    return 0x000FF;
                }
                str = str.Substring(str.IndexOf("0xFF") + 2, 5);
                char[] c = str.ToCharArray();
                int[] b = new int[5];
                for (int i = 0; i < 5; i++)
                {
                    b[i] = HexChar(c[i]);
                }
                a = b[0] * 16 * 16 * 16 * 16 + b[1] * 16 * 16 * 16 + b[2] * 16 * 16 + b[3] * 16 + b[4];
                return a;
            }
            catch
            {
                return a;
            }

        }

        public bool Open()
        {
            if (rs232.IsOpen)
            {
                rs232.Close();
            }
            //rs232.Close();
            System.Threading.Thread.Sleep(100);
            try
            {
                rs232.Open();
                return rs232.IsOpen;
            }
            catch (Exception exp)
            {
                FileWriter.WriteLog("Serials port did not open!");//写入到LOG文件
                if (rs232.IsOpen)
                {
                    rs232.Close();
                }
                //rs232.Close();
                System.Threading.Thread.Sleep(100);
                try
                {
                    rs232.Open();
                    return rs232.IsOpen;
                }
                catch (Exception ex)
                {
                    FileWriter.WriteLog("Serials port did not open!");//写入到LOG文件
                    return false;
                }

            }

        }

        public bool GetFirmwareVer()
        {
            if (rs232.IsOpen)
            {
                rs232.Write("GetFirmwareVer\r");
                if (this.Read() == "\r\n001\0")
                {
                    return true;
                }
            }
            return false;
        }

        /*XX：output port，X：status
         *0 is open, 1 is close
         *例如，WriteDO 0x01 0x00\r就是设置端口1有效
         */
        public bool WriteDO(int bitNum, bool isSet, int trycnt = 6)
        {
            lock (loc)
            {
                while (trycnt >= 1)
                {
                    try
                    {
                        int stattus = isSet ? 1 : 0;
                        int data = stattus;
                        string cmd = "WriteDO 0x" + bitNum.ToString("X2") + " 0x" + stattus.ToString("X2") + "\r\n";
                        rs232.Write(cmd);
                        Thread.Sleep(50);
                        var s = rs232.ReadTo(">");
                        //var s = this.Read();
                        //var sps = s.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                        //if ((sps.Length >= 2 && sps[1] == "OK") || (sps.Length >= 4 && sps[2] == "OK"))
                        if (s.Contains("OK"))
                        {
                            FileWriter.WriteLog(string.Format("IOboard " + Port + " WriteDO :{0} 成功 value:{1}", bitNum,s));
                            return true;
                        }
                        else
                        {
                            Thread.Sleep(200);
                            rs232.ReadExisting();
                            trycnt -= 1;
                            FileWriter.WriteLog(string.Format("IOboard " + Port + " WriteDO :{0} 失败 Value:{1}", bitNum,s));
                        }
                    }
                    catch (Exception ex)
                    {
                        trycnt -= 1;
                        Console.WriteLine("Exception trycount:" + trycnt);
                        FileWriter.WriteLog(string.Format("IOboard {0} WriteDO IO :{1}  Exception :{2}  ", Port, bitNum.ToString(), ex.Message));//写入到LOG文件
                    }
                    Thread.Sleep(5);
                }
                return false;
            }

        }
        /*读取输入口状态
         * ReadDI\r
         * XXXXX, Hex , port status
         * 
         */
        public string Read()
        {
            lock (loc)
            {
                string ret = string.Empty;
                try
                {
                    rs232.DiscardOutBuffer();
                    int n = rs232.BytesToRead;
                    if (n > 0)
                    {
                        Char[] buf = new Char[n];
                        rs232.Read(buf, 0, n);
                        rs232.DiscardInBuffer();
                        ret = new string(buf);
                        buf = null;//7.1
                    }
                }
                catch (Exception ex)
                {
                    FileWriter.WriteLog("rs232 Read " + " Exception :" + ex.Message);//写入到LOG文件
                }

                return ret;
            }
        }
        public void Close()
        {
            lock (loc)
            {
                try
                {
                    if (rs232.IsOpen)
                    {
                        rs232.Close();
                        rs232.Dispose();
                    }
                }
                catch (Exception ex)
                {

                    FileWriter.WriteLog("rs232 Close " + " Exception:" + ex.Message);//写入到LOG文件
                }
                
            }
            

        }

        #endregion

    }
}
