using ProjectBase.Data.Logs;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SIASUN.Autopilot.GNSS
{
    public class SerialPortBase
    {
        public event EventSerialDataReceiveHandler serialDataReceived;

        private SerialPort serialPort;

        private Thread thread;

        volatile bool _keepReading;

        /// <summary>
        /// 串口通信
        /// </summary>
        /// <param name="PortNumber">端口号</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="DataBits">数据位</param>
        public SerialPortBase(string PortNumber, int baudRate, int DataBits)
        {

            serialPort = new SerialPort();
            thread = null;
            _keepReading = false;
            serialPort.PortName = PortNumber;
            // 波特率
            serialPort.BaudRate = baudRate;
            // 数据位
            serialPort.DataBits = DataBits;
            // 两个停止位
            serialPort.StopBits = System.IO.Ports.StopBits.One;
            // 无奇偶校验位
            serialPort.Parity = System.IO.Ports.Parity.None;
            serialPort.ReadTimeout = 100;
            serialPort.WriteTimeout = -1;

            Open();
        }

        // 串口是否打开
        public bool IsOpen
        {
            get
            {
                return serialPort.IsOpen;
            }
        }

        /// <summary>
        /// 开始接收数据
        /// </summary>
        private void StartReading()
        {
            if (!_keepReading)
            {
                _keepReading = true;
                thread = new Thread(new ThreadStart(ReadPort));
                thread.Start();
            }
        }

        /// <summary>
        /// 停止读取数据
        /// </summary>
        public void StopReading()
        {
            if (_keepReading)
            {
                _keepReading = false;
                thread.Join();
                thread = null;
                LogHelper.log.Debug("关闭接收线程。");
            }
        }

        /// <summary>
        /// 数据接收
        /// </summary>
        private void ReadPort()
        {
            LogHelper.log.Debug("开始接收数据。");
            //START:
            while (_keepReading)
            {
                int offset = 0;
                int timeout = 0;
                byte[] readBuffer = new byte[1024 * 8];
                while (IsOpen)
                {
                    int count = serialPort.BytesToRead;
                    if (count > 0)
                    {
                        if ((offset + count) > 1024 * 8)
                        {
                            break;
                        }
                        int readCount = serialPort.Read(readBuffer, offset, count);
                        offset += readCount;
                        timeout = 0;
                    }
                    else
                    {
                        break;
                    }
                    if (timeout > 100)
                    {
                        break;
                    }
                    //Thread.Sleep(10);
                    timeout++;
                }
                string strData = System.Text.Encoding.Default.GetString(readBuffer).TrimEnd('\0');
                if (!string.IsNullOrEmpty(strData))
                {
                    if (serialDataReceived != null)
                    {
                        SerialPortDataReceiveEventArgs receive = new SerialPortDataReceiveEventArgs(strData);
                        serialDataReceived(receive);
                    }
                    LogHelper.log.Debug("接收数据完成 。");
                }
            }
        }

        /// <summary>
        /// 串口打开
        /// </summary>
        private void Open()
        {
            try
            {
                Close();
                serialPort.Open();
                if (serialPort.IsOpen)
                {
                    StartReading();
                }
                else
                {
                    LogHelper.log.Error("串口打开失败。");
                }
            }
            catch (Exception ex)
            {
                LogHelper.log.Error("打开串口时出现错误，错误为", ex);
                return;
            }

        }

        /// <summary>
        /// 串口关闭
        /// </summary>
        public void Close()
        {
            StopReading();
            serialPort.Close();
        }

        /// <summary>
        /// 串口写入数据
        /// </summary>
        /// <param name="send"></param>
        /// <param name="offSet"></param>
        /// <param name="count"></param>
        public void WritePort(byte[] send, int offSet, int count)
        {
            if (IsOpen)
            {
                LogHelper.log.Debug("开始写入数据。");
                serialPort.Write(send, offSet, count);
            }
        }


    }

    /// <summary>
    /// 串口接收数据
    /// </summary> 
    public delegate void EventSerialDataReceiveHandler(SerialPortDataReceiveEventArgs e);

    public class SerialPortDataReceiveEventArgs : EventArgs
    {
        public string Value { get; set; }

        public SerialPortDataReceiveEventArgs(string value)
        {
            this.Value = value;
        }
    }
}
