using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using System;
using System.IO.Ports;
using System.Text;

namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.SMIFs.Fortrend
{
    public class SerialPortEx
    {
        #region 变量属性
        private bool _retryConnect = true;

        private SerialPort _serialPort = new SerialPort();

        public event Action<string> OnReceivedEvent;

        //串口号
        private string _portName = "COM1";
        //波特率
        private int _baudRate = 9600;
        //校验位
        private Parity _parity = Parity.None;
        //停止位
        private StopBits _stopBits = StopBits.One;
        //数据位 
        private int _dataBits = 8;

        //分隔符
        public string Delimiter = "\r\n";

        private StringBuilder _buffer = new StringBuilder();

        private PeriodicJob _monitorThread;

        /// <summary>
        /// 串口号
        /// </summary>
        public string PortName
        {
            get { return _portName; }
            set { _portName = value; }
        }

        /// <summary>
        /// 波特率
        /// </summary>
        public int BaudRate
        {
            get { return _baudRate; }
            set { _baudRate = value; }
        }

        /// <summary>
        /// 奇偶校验位
        /// </summary>
        public Parity Parity
        {
            get { return _parity; }
            set { _parity = value; }
        }

        /// <summary>
        /// 数据位
        /// </summary>
        public int DataBits
        {
            get { return _dataBits; }
            set { _dataBits = value; }
        }

        /// <summary>
        /// 停止位
        /// </summary>
        public StopBits StopBits
        {
            get { return _stopBits; }
            set { _stopBits = value; }
        }
        #endregion

        #region 串口关闭/打开
        /// <summary>
        /// 端口是否已经打开
        /// </summary>
        public bool IsOpen => _serialPort != null ? _serialPort.IsOpen : false;

        #region 构造函数
        /// <summary>
        /// 无参构造函数
        /// </summary>
        public SerialPortEx()
        {
            BoundEvents();
        }

        public SerialPortEx(string portName)
        {
            this._portName = portName;

            BoundEvents();
        }

        /// <summary>
        /// 参数构造函数（使用枚举参数构造）
        /// </summary>
        ///  /// <param name="portName">串口号</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">奇偶校验位</param>
        /// <param name="stopBits">停止位</param>
        /// <param name="dataBits">数据位</param>

        public SerialPortEx(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
        {
            this._portName = portName;
            this._baudRate = baudRate;
            this._parity = parity;
            this._dataBits = dataBits;
            this._stopBits = stopBits;

            BoundEvents();
        }

        /// <summary>
        /// 参数构造函数（使用字符串参数构造）
        /// </summary>
        ///  /// <param name="portName">串口号</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">奇偶校验位</param>
        /// <param name="stopBits">停止位</param>
        /// <param name="dataBits">数据位</param>
        public SerialPortEx(string portName, int baudRate, string parity, int dataBits, string stopBits)
        {
            this._portName = portName;
            this._baudRate = baudRate;
            this._dataBits = dataBits;
            this._parity = (Parity)Enum.Parse(typeof(Parity), parity);
            this._stopBits = (StopBits)Enum.Parse(typeof(StopBits), stopBits);

            BoundEvents();
        }

        private void BoundEvents()
        {
            _serialPort.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);
            _serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(OnErrorReceived);

            _monitorThread = new PeriodicJob(3000, OnMonitor,$"{_serialPort.PortName}", true);
        }
        #endregion

        public void Reset()
        {
            _retryConnect = true;
        }

        private bool OnMonitor()
        {
            try
            {
                if (_serialPort != null && !_serialPort.IsOpen)
                {
                    if (_retryConnect)
                    {
                        _retryConnect = false;
                        _serialPort.Open();

                        if (_serialPort.IsOpen)
                        {
                            LOG.Info($"Retry Connect PortName : {_serialPort?.PortName} success");
                        }
                    }
                }
            }
            catch (Exception)
            {

            }

            return true;
        }

        #region 事件处理函数
        /// <summary>
        /// 数据接收处理
        /// </summary>
        private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // 读取所有可用数据
            string data = _serialPort.ReadExisting();
            _buffer.Append(data);

            string bufferContent = _buffer.ToString();
            int delimiterIndex;

            // 循环处理所有完整的消息
            while ((delimiterIndex = bufferContent.IndexOf(Delimiter)) != -1)
            {
                string msg = bufferContent.Substring(0, delimiterIndex + Delimiter.Length);
                // 移除处理过的数据和分隔符
                _buffer.Remove(0, delimiterIndex + Delimiter.Length); 
                // 更新缓冲区内容
                bufferContent = _buffer.ToString(); 

                // 处理消息（注意跨线程调用）
                OnReceivedEvent?.Invoke(msg);
            }
        }

        /// <summary>
        /// 错误处理函数
        /// </summary>
        public virtual void OnErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            LOG.Error($"{_serialPort.PortName}" + e.ToString());
        }
        #endregion

        /// <summary>
        /// 打开端口
        /// </summary>
        /// <returns></returns>
        public void Connect()
        {
            try
            {
                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();
                }

                _serialPort.PortName = _portName;
                _serialPort.BaudRate = _baudRate;
                _serialPort.Parity = _parity;
                _serialPort.DataBits = _dataBits;
                _serialPort.StopBits = _stopBits;

                _serialPort.ReadBufferSize = 4096;
                _serialPort.WriteBufferSize = 4096;

                _serialPort.Open();
            }
            catch (Exception ex)
            {
                LOG.Error(ex.Message, ex);
            }
        }

        /// <summary>
        /// 关闭端口
        /// </summary>
        public void Close()
        {
            try
            {
                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();
                }
            }
            catch (Exception ex)
            {
                LOG.Error(ex.Message, ex);
            }
        }

        /// <summary>
        /// 丢弃来自串行驱动程序的接收和发送缓冲区的数据
        /// </summary>
        public void DiscardBuffer()
        {
            _serialPort.DiscardInBuffer();
            _serialPort.DiscardOutBuffer();
        }
        #endregion

        #region 写入数据
        public bool Send(string sendMsg)
        {
            try
            {
                if (_serialPort.IsOpen)
                {
                    byte[] sendBytes = Encoding.UTF8.GetBytes(sendMsg);
                    _serialPort.Write(sendBytes, 0, sendBytes.Length);

                    return true;
                }
                else
                {
                    LOG.Error($"{_serialPort.PortName} is not open");
                    return false;
                }
            }
            catch (Exception ex)
            {
                LOG.Error(ex.Message,ex);
                return false;
            }
        }
        #endregion
    }
}
