using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YG.Device
{
    public class DeviceSerial : DeviceList
    {
        public override event RunMessage Msg;
        public override event RunState rState;
        System.IO.Ports.SerialPort serialPort;
        private SendState sendState;
        int SendCount = 0;
        int leng = 0;
        byte[] bt;
        private bool _ison = false;
        /// 
        /// 串口超时时间
        /// 
        public override bool IsOn
        {
            get { return _ison; }
            set
            {
                if (_ison != value)
                {
                    if (rState != null)
                    {
                        rState.Invoke(this.DeviceName, value); _ison = value;
                    }
                }
            }
        }
        public override void DeviceState()
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    System.Threading.Thread.Sleep(1000);
                    try
                    {
                        if (serialPort.IsOpen) { IsOn = true; }
                        else { IsOn = false; serialPort.Open(); }
                    }
                    catch
                    {
                        IsOn = false;
                        serialPort.Open();
                    }
                    finally
                    {
                    }
                }
            });
        }
        /// 
        /// 
        /// 
        /// 串口名称
        /// 波特率
        public DeviceSerial(string portname, int buard, int outtime = 2500)
        {
            serialPort = new System.IO.Ports.SerialPort(portname, buard);
            serialPort.DataReceived += SerialPort_DataReceived;
            serialPort.ReadTimeout = 100;
            serialPort.WriteTimeout = 100;
            timeout = outtime;
            this.DeviceName = portname;
        }
        public override void DeviceCheck()
        {
            System.Threading.Thread.Sleep(timeout);
            while (sendState == SendState.SendNoReceive)
            {
                serialPort.Write(SendValue.ToString());
                base.DeviceSend(SendValue);
                //一般情况下在延迟一段时间之后, 如果没有收到串口反馈的指令,那么下次发送也很难再接受到反馈, 所以下边默认延迟1500毫秒
                System.Threading.Thread.Sleep(1500);
                SendCount++;
                if (SendCount > 3)
                {
                    if (Msg != null)
                    {
                        Msg.Invoke(this.DeviceName, SendValue.Replace("\r", "").Replace("\n", ""), "连续发送三次数据没有得到回应");
                        sendState = SendState.StartSend;
                    }
                }
            }
        }
        public override void DeviceClose()
        {
            if (serialPort.IsOpen)
                serialPort.Close();
            base.DeviceClose();
        }
        public override void DeviceInit()
        {
            sendState = SendState.StartSend;
            IsOn = true;
            IsOn = false;
        }
        public override void DeviceOpen()
        {
            try
            {
                if (!serialPort.IsOpen)
                    serialPort.Open();
            }
            catch
            {
                YG.Log.Instance.WriteLogAdd(serialPort.PortName + "打开失败");
                System.Windows.Forms.MessageBox.Show(serialPort.PortName + "打开失败");
            }
            base.DeviceOpen();
        }
        public override void DeviceSend(object ob)
        {
            try
            {
                SendCount = 0;
                SendValue = ob.ToString();
                serialPort.Write(ob.ToString());
                base.DeviceSend(ob);
                sendState = SendState.SendNoReceive;
                Task.Factory.StartNew(() =>
                {
                    if (timeout > 0)
                    {
                        //  DeviceCheck();
                    }
                });
            }
            catch (Exception ex)
            {
                Log.Instance.WriteLogAdd("串口打开失败:" + ex.Message);
            }
        }
        private void SerialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            System.Threading.Thread.Sleep(50);
            sendState = SendState.Received;
            if (Msg != null)
            {
                sendState = SendState.Received;
                // if (Msg != null)
                {
                    leng = serialPort.BytesToRead;
                    bt = new byte[leng];
                    serialPort.Read(bt, 0, bt.Length);
                    Task.Factory.StartNew(() => {
                        Msg?.Invoke(this.DeviceName, SendValue.Replace("\r", "").Replace("\n", ""), Encoding.Default.GetString(bt)); });
                    YG.Log.Instance.WriteLogAdd(string.Format("{0}:接受到信息{1}", serialPort.PortName, Encoding.Default.GetString(bt)));
                }
                // Msg.Invoke(this.DeviceName, serialPort.ReadLine());
            }
        }
    }
}