using MegaRobo.Connections;
using MegaRobo.Contract;
using MegaRobo.ControlDevices.Abstractions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MegaRobo.C00225155.ControlDevices.USBScanner
{
    public class USBScannerService : ConnectorBase
    {
        public SerialPortService MegaSerialPort { get; set; }

        public bool IsConnected => this.MegaSerialPort?.IsOpen ?? false;

        /// <summary>
        /// 扫描仪数据接收事件（外部可订阅，实时获取串口数据）
        /// </summary>
        public event EventHandler<Message> ScannerDataReceived;

        #region Base
        public override async Task<string> Initialize(ICoreService coreService, params object[] args)
        {
            await Task.Delay(0);
            this.CoreService = coreService;
            if (args != null && args.Length > 0 && args[0] is string portName)
            {
                this.SetConnection(portName);
            }
            //else
            //{
            //    throw new ArgumentException("初始化失败：未传入有效的串口名称（portName）");
            //}
            return string.Empty;
        }


        private void SetConnection(string portName)
        {
            // 若已有串口实例，先断开并清理
            if (MegaSerialPort != null)
            {
                Disconnect();
            }
            this.MegaSerialPort = new SerialPortService(portName);
            this.Connection();
        }

        public string Connection()
        {
            try
            {
                if (MegaSerialPort != null && !MegaSerialPort.IsOpen)
                {
                    this.MegaSerialPort.Open();
                    // 2. 连接成功后订阅串口DataReceived事件（先取消再订阅，防止重复）
                    MegaSerialPort.DataReceived -= MegaSerialPort_DataReceived; // 取消旧订阅
                    MegaSerialPort.DataReceived += MegaSerialPort_DataReceived; // 新订阅
                }
                    
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

            return this.MegaSerialPort.IsOpen ? null : "连接异常";
        }

        public Task<string> ConnectionAsync()
        {
            return Task.Run(this.Connection);
        }

        public bool Disconnect()
        {
            if (MegaSerialPort != null)
            {
                // 3. 断开连接前取消事件订阅（避免内存泄漏）
                MegaSerialPort.DataReceived -= MegaSerialPort_DataReceived;
                MegaSerialPort.Dispose(); // 触发SerialPortService的Close和资源释放
            }
            return true;
        }

        public void Dispose()
        {
            this.Disconnect();
            this.MegaSerialPort = null;
        }
        #endregion Base

        /// <summary>
        /// 串口DataReceived事件的处理方法（自动触发）
        /// </summary>
        private void MegaSerialPort_DataReceived(object sender, Message msg)
        {
            if (msg == null || msg.Data == null || msg.Data.Length == 0)
                return;

            string receivedData = msg.ReadString(SerialPortDataFormat.Char); // 用串口配置的格式解析

            // --------------------------
            // 步骤2：对外透传数据（触发自定义事件）
            // 外部订阅ScannerDataReceived即可实时获取数据
            // --------------------------
            OnScannerDataReceived(msg);
        }

        /// <summary>
        /// 触发自定义事件（线程安全的事件触发方式）
        /// </summary>
        protected virtual void OnScannerDataReceived(Message msg)
        {
            // 临时保存事件引用，避免多线程下事件被注销后为空
            var handler = ScannerDataReceived;
            handler?.Invoke(this, msg);
        }

        public string SendAndReceive(string cmd, TimeSpan timeout)
        {
            string mReply = string.Empty;
            EventHandler<Message> tempHandler = (sender, msg) =>
            {
                mReply = msg.ReadString(SerialPortDataFormat.Char);
            };
            try
            {
                MegaSerialPort.DataReceived += tempHandler;
                MegaSerialPort.WriteLine(cmd);
                Stopwatch stopwatch = Stopwatch.StartNew();
                while (string.IsNullOrEmpty(mReply) && stopwatch.Elapsed < timeout)
                {
                    Thread.Sleep(50);
                }
            }
            finally 
            {
                MegaSerialPort.DataReceived -= tempHandler;
            }
            return mReply;
        }

        public override async Task<ConnectionState> CheckConnected()
        {
            await Task.Delay(0);
            if (this.MegaSerialPort.IsOpen)
            {
                return ConnectionState.IsConnected;
            }
            else
            {
                return ConnectionState.NotConnected;
            }
        }

        public override async Task<ConnectionState> ReconnectAsync()
        {
            await Task.Delay(0);
            if (string.IsNullOrEmpty(await ConnectionAsync()))
            {
                return ConnectionState.IsConnected;
            }
            else
            {
                return ConnectionState.NotConnected;
            }
        }

    }
}
