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

namespace VIZ.Framework.Connection
{
    /// <summary>
    /// 串口终结点管理器
    /// </summary>
    public class SerialPortEndpointManager : IDisposable
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static ILog log = LogManager.GetLogger(typeof(SerialPortEndpointManager));

        /// <summary>
        /// 接收数据数组大小
        /// </summary>
        public const int RECV_BUFFER_SIZE = 1024 * 10;

        /// <summary>
        /// 串口终结点管理器
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="portName">端口</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">对象的奇偶校验位</param>
        /// <param name="dataBits">数据位值</param>
        /// <param name="stopBits">使用停止位</param>
        public SerialPortEndpointManager(string key, string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
        {
            this.Key = key;
            this.SerialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
            this.SerialPort.DataReceived += SerialPort_DataReceived;
        }

        /// <summary>
        /// 键
        /// </summary>
        public string Key { get; private set; }

        /// <summary>
        /// 串口
        /// </summary>
        public SerialPort SerialPort { get; private set; }

        /// <summary>
        /// 包处理器
        /// </summary>
        public IConnPackageProvider PackageProvider { get; set; }

        /// <summary>
        /// 串口连接
        /// </summary>
        public SerialPortConnection SerialPortConnection { get; internal set; }

        /// <summary>
        /// 打开串口
        /// </summary>
        public void Open()
        {
            this.SerialPort.Open();
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="buffer">数据</param>
        public void Send(byte[] buffer)
        {
            this.SerialPort.Write(buffer, 0, buffer.Length);
        }

        /// <summary>
        /// 销毁
        /// </summary>
        public void Dispose()
        {
            this.SerialPort?.Close();
            this.SerialPort?.Dispose();
            this.SerialPort = null;
        }

        /// <summary>
        /// 接收数据触发
        /// </summary>
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            while (true)
            {
                byte[] buffer = new byte[RECV_BUFFER_SIZE];
                int read = this.SerialPort.Read(buffer, 0, RECV_BUFFER_SIZE);

                if (read <= 0)
                    break;

                ConnPackageInfo package = new ConnPackageInfo();
                package.PortName = this.SerialPort.PortName;
                package.Data = buffer;
                package.DataSize = read;

                if (this.PackageProvider == null)
                    continue;

                try
                {
                    this.PackageProvider.Execute(package);
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                }
            }
        }
    }
}
