using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using FundamentalLib;
using Medulla;

namespace MedullaAdapter
{
    public class EmbeddedCommunication
    {
        private SerialPort _port;

        private byte[] _receiveBytes;

        private byte[] _receiveData;

        private const int BufferThreshold = 300; // 缓冲区大小阈值

        private List<byte> _buffer = new List<byte>(); // 缓存接收到的数据

        public bool CommunicationError = false;

        private DateTime _lastTime = DateTime.Now;

        private MCUInterface<DiverCartDefinition> _interface;

        public EmbeddedCommunication(string name, int baudRate)
        {
            _interface = new MCUInterface<DiverCartDefinition>();
            _port = new SerialPort();
            _port.PortName = name; // 根据你的实际串口名称修改
            _port.BaudRate = baudRate;
            _port.Parity = Parity.None;
            _port.DataBits = 8;
            _port.StopBits = StopBits.One;
            _port.Handshake = Handshake.None;
            _port.Open();
            _port.DataReceived += OnDataReceived;
        }

        public void SendMessage(byte[] data)
        {
            Hedingben.ToastText($"send to mcu:{BitConverter.ToString(data)}","DiverSend");
            _port.Write(data, 0, data.Length);
        }

        public byte[] GetMessage()
        {
            return _receiveBytes;
        }

        private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                int bytesToRead = _port.BytesToRead;
                byte[] buffer = new byte[bytesToRead];
                var startRead = DateTime.Now;
                _port.Read(buffer, 0, bytesToRead);
                var time = DateTime.Now - startRead;
                // 将新接收到的数据添加到缓冲区
                startRead = DateTime.Now;
                _buffer.AddRange(buffer);
                var time2 = DateTime.Now - startRead;
                Hedingben.ToastText($"buffer length:{_buffer.Count}","bufferDebug");
                DLog.Log($"buffer length:{_buffer.Count}");
                //if (_buffer.Count > BufferThreshold)
                //{
                //    _buffer.Clear();
                //    return;
                //}

                // 尝试解析缓冲区中的报文
                var parseTime = DateTime.Now;
                ParseBuffer();
                var time3 = DateTime.Now - parseTime;
                Hedingben.ToastText(
                    $"读取报文时间:{time.TotalMilliseconds},增加到缓存区:{time2.TotalMilliseconds},处理时间:{time3.TotalMilliseconds}",
                    "timeDebug1");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读取串口数据时发生错误: {ex.Message}"+ex.StackTrace);
            }
        }
        private void ParseBuffer()
        {
            while (_buffer.Count >= 7) // 报文的最小长度是 7
            {
                // 查找报文头部
                var findTime = DateTime.Now;
                int startIndex = _buffer.FindIndex(0, b => b == 0xBB);
                var time1 = DateTime.Now - findTime;
                if (startIndex == -1)
                {
                    // 如果没有找到头部或剩余长度不足最小报文长度，结束解析
                    _buffer.Clear();
                    return;
                }

                // 确保头部后还有至少 6 个字节
                if (startIndex + 1 >= _buffer.Count || _buffer[startIndex + 1] != 0xAA)
                {
                    // 如果第二字节不是 0xAA，丢弃无效字节
                    _buffer.RemoveAt(startIndex);
                    continue;
                }

                // 检查数据段长度
                if (startIndex + 4 >= _buffer.Count) break; // 数据不足，等待下次接收
                int dataLength = _buffer[startIndex + 2] | (_buffer[startIndex + 3] << 8);

                // 计算报文总长度
                int totalLength = dataLength + 7;

                // 检查总长度是否足够
                if (startIndex + totalLength > _buffer.Count) break; // 数据不足，等待下次接收

                // 检查尾部是否是 0xCC 0xEE
                if (_buffer[startIndex + totalLength - 2] == 0xCC && _buffer[startIndex + totalLength - 1] == 0xEE)
                {
                    var time2 = DateTime.Now - findTime;
                    var copyTime = DateTime.Now;
                    // 提取完整报文
                    _receiveBytes = _buffer.Skip(startIndex).Take(totalLength).ToArray();
                    var time3 = DateTime.Now - copyTime;
                    if (_receiveBytes[5] == 0xA0)
                    {
                        var dataLength1 = BitConverter.ToUInt32(_receiveBytes, 6);
                        var data1 = new byte[dataLength1];
                        Array.Copy(_receiveBytes, 14, data1, 0, dataLength1);
                        var notifyTime = DateTime.Now;
                        MCUInterface<DiverCartDefinition>.NotifyLowerData("default", data1);
                        var time4 = DateTime.Now - notifyTime;
                        var logBytes = new byte[BitConverter.ToInt32(_receiveBytes, 10)];
                        var memorySize = BitConverter.ToInt32(_receiveBytes, 6);
                        if (logBytes.Length > 0)
                        {
                            Array.Copy(_receiveBytes, 14 + memorySize, logBytes, 0, logBytes.Length);
                            string log = System.Text.Encoding.ASCII.GetString(logBytes);
                            string[] result = log.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
                            for (int i = 0; i < result.Length; i++)
                            {
                                Hedingben.ToastText(result[i], $"mcuLog" + i);
                            }
                        }

                        Hedingben.ToastText(
                            $"find head time:{time1.TotalMilliseconds},find total time:{time2.TotalMilliseconds},copy time:{time3.TotalMilliseconds},notify time:{time4.TotalMilliseconds}","timeDebug2");
                    }

                    Hedingben.ToastText(
                        $"receive from mcu:{BitConverter.ToString(_receiveBytes)},time:{(DateTime.Now - _lastTime).TotalMilliseconds}",
                        "DiverReceive");
                    if ((DateTime.Now - _lastTime).TotalMilliseconds > 200)
                    {
                        Hedingben.ToastText($"{(DateTime.Now - _lastTime).TotalMilliseconds}ms no message from diver","DiverTimeout");
                    }
                    _lastTime = DateTime.Now;
                    // 从缓冲区中移除已解析的报文
                    _buffer.RemoveRange(0, startIndex + totalLength);
                    return; // 成功解析一条报文后退出本轮解析

                }
                else
                {
                    // 如果尾部无效，丢弃头部并继续解析
                    DLog.Log("DIVER报文无效");
                    Console.WriteLine("DIVER报文无效");
                    var errorBytes = _buffer.Skip(startIndex).Take(totalLength).ToArray();
                    DLog.Log("错误报文"+string.Join(" ",errorBytes.Select(p=>$"{p:X2}")));
                    _buffer.RemoveAt(startIndex);
                }
                
            }
        }

    }
}
