using Common.Attributes;
//using DeviceCommand.Interface;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using static Common.Attributes.ATSCommandAttribute;

namespace DeviceCommand.Base
{
    [ATSCommand]
    [DeviceCategory("全部驱动")] // 添加分类属性
    public class Serial_Port
    {
        public string PortName { get; set; } = "COM1";
        public int BaudRate { get; set; } = 9600;
        public int DataBits { get; set; } = 8;
        public StopBits StopBits { get; set; } = StopBits.One;
        public Parity Parity { get; set; } = Parity.None;
        public int ReadTimeout { get; set; } = 3000;
        public int WriteTimeout { get; set; } = 3000;
        public SerialPort _SerialPort { get; set; } = new SerialPort();

        /// <summary>
        /// 创建并配置串口实例
        /// </summary>
        /// <param name="portName">串口名称（如"COM1"）</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="dataBits">数据位,配置默认值：8</param>
        /// <param name="stopBits">停止位,配置默认值：StopBits.One</param>
        /// <param name="parity">校验位（根据设备需求设置）,配置默认值：Parity.None</param>
        /// <param name="readTimeout">读取超时</param>
        /// <param name="writeTimeout">写入超时</param>
        public Serial_Port CreateDevice(string portName, int baudRate
            , int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None
            , int readTimeout = 3000, int writeTimeout = 3000)
        {
            PortName = portName;
            BaudRate = baudRate;
            DataBits = dataBits;
            StopBits = stopBits;
            Parity = parity;
            ReadTimeout = readTimeout;
            WriteTimeout = writeTimeout;
            return this;
        }

        /// <summary>
        /// 修改串口实例参数
        /// </summary>
        /// <param name="serialPort">串口实例</param>
        /// <param name="PortName">串口名称（如"COM1"）</param>
        /// <param name="BaudRate">波特率</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        /// <param name="parity">校验位（根据设备需求设置）</param>
        /// <param name="ReadTimeout">读取超时</param>
        /// <param name="WriteTimeout">写入超时</param>
        public static void ChangeDeviceConfig(Serial_Port serialPort, string PortName, int BaudRate
            , int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None
            , int ReadTimeout = 3000, int WriteTimeout = 3000)
        {
            // 更新配置串口实例参数
            serialPort.PortName = PortName;       // 串口名称（如"COM1"）
            serialPort.BaudRate = BaudRate;      // 波特率
            //serialPort.ReadTimeout = ReadTimeout;
            //serialPort.WriteTimeout = WriteTimeout; 
            serialPort.Parity = parity;      // 校验位（根据设备需求设置）
            serialPort.DataBits = dataBits;              // 数据位
            serialPort.StopBits = stopBits;   // 停止位

            if (ReadTimeout > 0)
                serialPort.ReadTimeout = ReadTimeout; // 读取超时
            if (WriteTimeout > 0)
                serialPort.WriteTimeout = WriteTimeout;// 写入超时

        }

        /// <summary>
        /// 串口连接
        /// </summary>
        /// <param name="serialPort">串口实例</param>
        /// <param name="ct">支持中途取消发送指令</param>
        public static async Task<bool> ConnectAsync(Serial_Port serialPort, CancellationToken ct = default)
        {
            if (serialPort._SerialPort.PortName != serialPort.PortName
                || serialPort._SerialPort.BaudRate != serialPort.BaudRate
                || serialPort._SerialPort.Parity != serialPort.Parity
                || serialPort._SerialPort.DataBits != serialPort.DataBits
                || serialPort._SerialPort.StopBits != serialPort.StopBits
                || serialPort._SerialPort.ReadTimeout != serialPort.ReadTimeout
                || serialPort._SerialPort.WriteTimeout != serialPort.WriteTimeout)
            {

                // 关闭现有连接并重新配置
                serialPort._SerialPort.Close();

                //更新串口配置
                serialPort._SerialPort.PortName = serialPort.PortName;
                serialPort._SerialPort.BaudRate = serialPort.BaudRate;
                serialPort._SerialPort.Parity = serialPort.Parity;
                serialPort._SerialPort.DataBits = serialPort.DataBits;
                serialPort._SerialPort.StopBits = serialPort.StopBits;
                serialPort._SerialPort.ReadTimeout = serialPort.ReadTimeout;
                serialPort._SerialPort.WriteTimeout = serialPort.WriteTimeout;

                // 重新打开串口
                serialPort._SerialPort.Open();

            }
            else
            {
                // 检查串口是否已打开
                if (!serialPort._SerialPort.IsOpen)
                {
                    // 打开串口
                    serialPort._SerialPort.Open();
                }
            }
            return true;
        }

        /// <summary>
        /// 串口关闭
        /// </summary>
        /// <param name="serialPort">串口实例</param>
        public static void Close(Serial_Port serialPort)
        {
            if (serialPort._SerialPort.IsOpen)
            {
                // 关闭串口连接
                serialPort._SerialPort.Close();
                //Console.WriteLine("串口已关闭");
            }
        }

        /// <summary>
        /// 串口发送byte类型数据信息
        /// </summary>
        /// <param name="serialPort">串口实例</param>
        /// <param name="bytes">发送的数据信息为byte类型</param>
        /// <param name="ct">支持中途取消发送指令</param>
        public static async Task SendAsync(Serial_Port serialPort, byte[] bytes, CancellationToken ct = default)
        {
            if (!serialPort._SerialPort.IsOpen) return;

            // 获取写入超时时间
            var timeoutMs = serialPort.WriteTimeout;
            if (timeoutMs <= 0)
            {
                serialPort._SerialPort.Write(bytes, 0, bytes.Length);  // 向串口写入字节数据
                return;
            }

            var sendTask = Task.Run(() =>
            {
                // 向串口写入字节数据
                serialPort._SerialPort.Write(bytes, 0, bytes.Length);
            }, ct);
            var timeoutTask = Task.Delay(timeoutMs, ct);

            var completedTask = await Task.WhenAny(sendTask, timeoutTask);
            if (completedTask == timeoutTask)
            {
                throw new TimeoutException($"串口通讯异常：写入操作在 {timeoutMs} ms内未完成");
            }

            await sendTask;

            //if (serialPort._SerialPort.IsOpen)
            //{
            //try
            //{
            //    // 异步发送数据到串口
            //    await Task.Run(() =>
            //    {
            //        serialPort._SerialPort.Write(bytes, 0, bytes.Length);  // 向串口写入字节数据
            //    }, ct);
            //}
            //catch (Exception ex)
            //{
            //    // 异常处理
            //    //Console.WriteLine($"发送数据失败: {ex.Message}");
            //    MessageBox.Show($"串口发送数据失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            //}
            //}
            //else
            //{
            //    //Console.WriteLine("串口未打开");
            //    MessageBox.Show($"串口未打开", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            //}
        }

        /// <summary>
        /// 串口发送字符串类型数据信息
        /// </summary>
        /// <param name="serialPort">串口实例</param>
        /// <param name="str">发送的数据信息为字符串类型</param>
        /// <param name="ct">支持中途取消发送指令</param>
        public static async Task SendAsync(Serial_Port serialPort, string str, CancellationToken ct = default)
        {
            if (!serialPort._SerialPort.IsOpen) return;

            // 将字符串转换为字节数组
            byte[] bytes = Encoding.UTF8.GetBytes(str);

            // 获取写入超时时间
            var timeoutMs = serialPort.WriteTimeout;
            if (timeoutMs <= 0)
            {
                serialPort._SerialPort.Write(bytes, 0, bytes.Length);
                return;
            }

            var sendTask = Task.Run(() =>
            {
                // 向串口写入字节数据
                serialPort._SerialPort.Write(bytes, 0, bytes.Length);
            }, ct);
            var timeoutTask = Task.Delay(timeoutMs, ct);

            var completedTask = await Task.WhenAny(sendTask, timeoutTask);
            if (completedTask == timeoutTask)
            {
                throw new TimeoutException($"串口通讯异常：写入操作在 {timeoutMs} ms内未完成");
            }

            await sendTask;
        }

        /// <summary>
        /// 串口读取byte类型数据信息
        /// </summary>
        /// <param name="serialPort">串口实例</param>
        /// <param name="buffer">读取的数据信息为byte数组类型</param>
        /// <param name="ct">支持中途取消发送指令</param>
        public static async Task<byte[]> ReadAsync(Serial_Port serialPort, byte[] buffer, CancellationToken ct = default)
        {
            if (!serialPort._SerialPort.IsOpen) return null;

            int bytesRead = 0;

            // 获取写入超时时间
            var timeoutMs = serialPort.ReadTimeout;
            if (timeoutMs <= 0)
            {
                return await ReadByte(serialPort, buffer, ct);
                //while (bytesRead < buffer.Length)
                //{
                //    if (serialPort._SerialPort.BytesToRead > 0)
                //    {
                //        bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead);
                //    }
                //}
                //return buffer;
            }

            //var readTask = Task.Run(() =>
            //{
            //    while (bytesRead < buffer.Length)
            //    {
            //        if (serialPort._SerialPort.BytesToRead > 0)
            //        {
            //            bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead);
            //        }
            //    }
            //}, ct);
            var readTask = ReadByte(serialPort, buffer, ct);
            var timeoutTask = Task.Delay(timeoutMs, ct);

            var completedTask = await Task.WhenAny(readTask, timeoutTask);
            if (completedTask == timeoutTask)
            {
                throw new TimeoutException($"串口通讯异常：读取操作在 {timeoutMs} ms内未完成");
            }

            return buffer;


            //try
            //{
            //    // 异步读取串口数据
            //    await Task.Run(() =>
            //    {
            //        while (bytesRead < buffer.Length)
            //        {
            //            if (serialPort._SerialPort.BytesToRead > 0)
            //            {
            //                bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead);
            //            }
            //        }
            //    }, ct);
            //}
            //catch (Exception ex)
            //{
            //    //Console.WriteLine($"读取数据失败: {ex.Message}");
            //    MessageBox.Show($"读取串口数据失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            //    return null;
            //}
            //return buffer;
        }

        public static async Task<byte[]> ReadByte(Serial_Port serialPort, byte[] buffer, CancellationToken ct)
        {
            int bytesRead = 0;
            while (bytesRead < buffer.Length)
            {
                if (serialPort._SerialPort.BytesToRead > 0)
                {
                    bytesRead += serialPort._SerialPort.Read(buffer, bytesRead, buffer.Length - bytesRead);
                }
            }
            return buffer;
        }

        /// <summary>
        /// 串口读取字符串类型数据信息
        /// </summary>
        /// <param name="serialPort">串口实例</param>
        /// <param name="delimiter">读取的数据信息为字符串类型,string delimiter = "\n"</param>
        /// <param name="ct">支持中途取消发送指令</param>
        public static async Task<string> ReadAsync(Serial_Port serialPort, string delimiter = "\n", CancellationToken ct = default)
        {
            if (!serialPort._SerialPort.IsOpen) return null;

            // 获取写入超时时间
            var timeoutMs = serialPort.ReadTimeout;
            if (timeoutMs <= 0)
            {
                return await ReadDefaultString(serialPort, delimiter, ct);
            }

            var readTask = ReadDefaultString(serialPort, delimiter, ct);
            var timeoutTask = Task.Delay(timeoutMs, ct);

            var completedTask = await Task.WhenAny(readTask, timeoutTask);
            if (completedTask == timeoutTask)
            {
                throw new TimeoutException($"串口通讯异常：读取操作在 {timeoutMs} ms内未完成");
            }

            return await readTask;

            //try
            //{
            //    // 异步读取串口数据
            //    await Task.Run(() =>
            //    {
            //        while (true)
            //        {
            //            if (ct.IsCancellationRequested)
            //                return;

            //            if (serialPort._SerialPort.BytesToRead > 0)
            //            {
            //                bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length);
            //                memoryStream.Write(buffer, 0, bytesRead);

            //                data = Encoding.UTF8.GetString(memoryStream.ToArray());
            //                int lineEndIndex = data.IndexOf(delimiter);

            //                // 找到分隔符，则返回数据
            //                if (lineEndIndex >= 0)
            //                {
            //                    data = data.Substring(0, lineEndIndex).Trim();
            //                    return;
            //                }
            //            }
            //        }
            //    }, ct);
            //}
            //catch (Exception ex)
            //{
            //    //Console.WriteLine($"读取串口数据失败: {ex.Message}");
            //    MessageBox.Show($"读取串口数据失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            //    return null;
            //}
            //return data;
        }

        private static async Task<string> ReadDefaultString(Serial_Port serialPort, string delimiter, CancellationToken ct)
        {
            delimiter ??= "\n";
            MemoryStream memoryStream = new();
            byte[] buffer = new byte[2048];
            int bytesRead = 0;
            string data = string.Empty;

            // 异步读取串口数据
            await Task.Run(() =>
            {
                while (true)
                {
                    if (ct.IsCancellationRequested)
                        return;

                    if (serialPort._SerialPort.BytesToRead > 0)
                    {
                        bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length);
                        memoryStream.Write(buffer, 0, bytesRead);

                        data = Encoding.UTF8.GetString(memoryStream.ToArray());
                        int lineEndIndex = data.IndexOf(delimiter);

                        // 找到分隔符，则返回数据
                        if (lineEndIndex >= 0)
                        {
                            data = data.Substring(0, lineEndIndex).Trim();
                            return;
                        }
                    }
                }
            }, ct);
            return data;
        }

        /// <summary>
        /// 串口读取字符串类型数据信息
        /// </summary>
        /// <param name="serialPort">串口实例</param>
        /// <param name="delimiter">读取的数据信息为字符串类型,string delimiter</param>
        /// <param name="ct">支持中途取消发送指令</param>
        public static async Task<string> ReadStrAsync(Serial_Port serialPort, string delimiter, CancellationToken ct = default)
        {
            if (!serialPort._SerialPort.IsOpen)
            {
                return null;  // 串口未打开，返回 null
            }

            // 获取写入超时时间
            var timeoutMs = serialPort.ReadTimeout;
            if (timeoutMs <= 0)
            {
                return await ReadString(serialPort, delimiter, ct);
            }

            var readTask = ReadString(serialPort, delimiter, ct);
            var timeoutTask = Task.Delay(timeoutMs, ct);

            var completedTask = await Task.WhenAny(readTask, timeoutTask);
            if (completedTask == timeoutTask)
            {
                throw new TimeoutException($"串口通讯异常：读取操作在 {timeoutMs} ms内未完成");
            }

            return await readTask;

            ////delimiter ??= "\n";  // 默认分隔符为换行符
            //MemoryStream memoryStream = new();
            //byte[] buffer = new byte[2048];
            //int bytesRead;
            //string data = string.Empty;

            //// 异步读取串口数据
            //await Task.Run(() =>
            //{
            //    while (true)
            //    {
            //        if (ct.IsCancellationRequested)
            //            return;

            //        if (serialPort._SerialPort.BytesToRead > 0)
            //        {
            //            // 从串口读取数据
            //            bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length);
            //            memoryStream.Write(buffer, 0, bytesRead);

            //            // 获取当前已读取的数据
            //            data = Encoding.UTF8.GetString(memoryStream.ToArray());

            //            // 查找分隔符
            //            int delimiterIndex = data.IndexOf(delimiter);
            //            if (delimiterIndex >= 0)
            //            {
            //                // 如果找到分隔符，则返回读取到的字符串
            //                data = data.Substring(0, delimiterIndex).Trim();
            //                return;
            //            }
            //        }
            //    }
            //}, ct);

            //try
            //{
            //    // 异步读取串口数据
            //    await Task.Run(() =>
            //    {
            //        while (true)
            //        {
            //            if (ct.IsCancellationRequested)
            //                return;

            //            if (serialPort._SerialPort.BytesToRead > 0)
            //            {
            //                // 从串口读取数据
            //                bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length);
            //                memoryStream.Write(buffer, 0, bytesRead);

            //                // 获取当前已读取的数据
            //                data = Encoding.UTF8.GetString(memoryStream.ToArray());

            //                // 查找分隔符
            //                int delimiterIndex = data.IndexOf(delimiter);
            //                if (delimiterIndex >= 0)
            //                {
            //                    // 如果找到分隔符，则返回读取到的字符串
            //                    data = data.Substring(0, delimiterIndex).Trim();
            //                    return;
            //                }
            //            }
            //        }
            //    }, ct);
            //}
            //catch (Exception ex)
            //{
            //    //Console.WriteLine($"读取串口数据时发生错误: {ex.Message}");
            //    MessageBox.Show($"读取串口数据时发生错误: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            //    return null;
            //}

            //return data;  // 如果没有数据返回，返回 null
        }

        private static async Task<string> ReadString(Serial_Port serialPort, string delimiter, CancellationToken ct)
        {
            //delimiter ??= "\n";
            MemoryStream memoryStream = new();
            byte[] buffer = new byte[2048];
            int bytesRead = 0;
            string data = string.Empty;

            // 异步读取串口数据
            await Task.Run(() =>
            {
                while (true)
                {
                    if (ct.IsCancellationRequested)
                        return;

                    if (serialPort._SerialPort.BytesToRead > 0)
                    {
                        bytesRead = serialPort._SerialPort.Read(buffer, 0, buffer.Length);
                        memoryStream.Write(buffer, 0, bytesRead);

                        data = Encoding.UTF8.GetString(memoryStream.ToArray());
                        int lineEndIndex = data.IndexOf(delimiter);

                        // 找到分隔符，则返回数据
                        if (lineEndIndex >= 0)
                        {
                            data = data.Substring(0, lineEndIndex).Trim();
                            return;
                        }
                    }
                }
            }, ct);
            return data;
        }

        /// <summary>
        /// 串口连接
        /// </summary>
        /// <param name="ct">取消令牌</param>
        /// <returns>连接结果</returns>
        public async Task<bool> ConnectAsync(CancellationToken ct = default)
        {
            return await ConnectAsync(this, ct);
        }

        /// <summary>
        /// 断开串口连接
        /// </summary>
        public void Disconnect()
        {
            Close(this);
        }

        /// <summary>
        /// 发送字符串到串口
        /// </summary>
        /// <param name="str">要发送的字符串</param>
        /// <param name="ct">取消令牌</param>
        public async Task SendStringAsync(string str, CancellationToken ct = default)
        {
            await SendAsync(this, str, ct);
        }

        /// <summary>
        /// 接收字符串直到遇到指定分隔符
        /// </summary>
        /// <param name="delimiter">分隔符</param>
        /// <param name="ct">取消令牌</param>
        /// <returns>接收到的字符串</returns>
        public async Task<string> ReceiveStringToAsync(string delimiter, CancellationToken ct = default)
        {
            return await ReadAsync(this, delimiter, ct);
        }

    }
}