using PTMedicalInsurance.Variables;
using RFID;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PTMedicalInsurance.Business.MetalKeyboard.JustTideEPP
{
    public  class MetalKeypadPasswordReaderOld
    {

        private int timeouts = 200000; 
        
        public void OpenKeyboard()
        {
            //打开串口
            if (JustTideEPPDrv.OpenCom(3, 9600) != 0)
            {
                Global.writeLog("打开串口失败");
            }
            else
            {
                Global.writeLog("打开串口成功");
            }
            //打开键盘
            if (JustTideEPPDrv.EnableKeyboard() != 0)
            {
                Global.writeLog("打开键盘失败");
            }
            else
            {
                Global.writeLog("打开键盘成功");
            }
            //轮询获取字符并发送到光标处
            if (GetAndSendPassword() != 0)
            {
                Global.writeLog("获取密码失败");
                return;
            }
            else
            {
                Global.writeLog("获取密码成功");
                return;
            }
           
        }


        public void CloseKeyboard()
        {
            //关闭键盘
            if (JustTideEPPDrv.DisableKeyboard() != 0)
            {
                Global.writeLog("关闭键盘失败");
            }
            else
            {
                Global.writeLog("关闭键盘成功");
            }
            //关闭串口
            if (JustTideEPPDrv.CloseCom() != 0)
            {
                Global.writeLog("关闭串口失败");
            }
            else
            {
                Global.writeLog("关闭串口成功");
            }
        }
        private int GetAndSendPassword()
        {
            char key = '\0';
            // 使用 Stopwatch 实现超时
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();

            try
            {
                // 主循环：持续轮询，直到超时
                while (stopwatch.ElapsedMilliseconds < timeouts) // timeouts 是您的超时毫秒数
                {
                    short result = JustTideEPPDrv.PinReportPressed(ref key, 1); // 非阻塞调用

                    if (result == 0) // 成功读取到按键
                    {
                        string hexStr = ((int)key).ToString("X2");

                        // --- 核心：发送字符到焦点窗口 ---
                        if (hexStr != "0D" && hexStr != "1B") // 排除回车和ESC
                        {
                            new SendMsg().SendText(key.ToString());
                        }
                        else if (hexStr == "0D") // 回车键 '#'
                        {
                            new SendMsg().SendText(key.ToString());
                            return 0; // 收到确认，成功返回
                        }
                        else if (hexStr == "1B") // ESC键
                        {
                            new SendMsg().SendText(key.ToString());
                            return 0; // 收到取消，也返回成功（或可返回特定码）
                        }
                    }
                    // else: result != 0 表示无按键，继续循环等待

                    // 关键：同步延迟，避免CPU空转
                    // 这会在当前线程上阻塞 50ms
                    System.Threading.Thread.Sleep(50);
                }

                // 如果走到这里，说明超时了
                // 可以选择发送超时信号或直接返回
                return -1; // 表示超时
            }
            catch (Exception ex)
            {
                // 捕获任何意外异常（虽然 PinReportPressed 可能不会抛出）
                // 可以记录日志
                // Logger.Error($"GetAndSendPassword error: {ex.Message}");
                return -99; // 表示未知错误
            }
            finally
            {
                stopwatch.Stop(); // 停止计时器
                                  // 如果需要，可以在这里执行清理工作
            }
        }
    }

    public class MetalKeypadPasswordReader : IDisposable
    {
        private CancellationTokenSource _listenCts;
        private Task _listenTask;
        private bool _isListening = false;
        private const int DEFAULT_TIMEOUT = 30000; // 30秒超时，可根据需要调整
        public int timeouts = DEFAULT_TIMEOUT; // 可以让调用方设置超时

        /// <summary>
        /// 打开串口和键盘，并启动后台监听（非阻塞）
        /// </summary>
        public void OpenKeyboard()
        {
            if (_isListening)
            {
                // 已经在监听，避免重复打开
                return;
            }

            // 1. 打开串口
            if (JustTideEPPDrv.OpenCom(3, 9600) != 0)
            {
                Global.writeLog("打开串口失败");
                return;
            }
            else
            {
                Global.writeLog("打开串口成功");
            }

            // 2. 打开键盘
            if (JustTideEPPDrv.EnableKeyboard() != 0)
            {
                Global.writeLog("打开键盘失败");
                JustTideEPPDrv.CloseCom(); // 清理
                return;
            }
            else
            {
                Global.writeLog("打开键盘成功");
            }

            // 3. 启动后台监听任务（关键：非阻塞）
            _listenCts = new CancellationTokenSource();
            _listenTask = Task.Run(() => ListenLoop(_listenCts.Token), _listenCts.Token);
            _isListening = true;

            // OpenKeyboard 方法立即返回，不会阻塞！
        }

        /// <summary>
        /// 后台监听循环 - 替代原来的 GetAndSendPassword
        /// </summary>
        private async Task ListenLoop(CancellationToken ct)
        {
            char key = '\0';
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();

            try
            {
                while (!ct.IsCancellationRequested && stopwatch.ElapsedMilliseconds < timeouts)
                {
                    short result = JustTideEPPDrv.PinReportPressed(ref key, 1);

                    if (result == 0)
                    {
                        string hexStr = ((int)key).ToString("X2");

                        // 发送字符到焦点窗口
                        if (hexStr != "0D" && hexStr != "1B")
                        {
                            new SendMsg().SendText(key.ToString());
                        }
                        else if (hexStr == "0D" || hexStr == "1B") // # 或 ESC
                        {
                            new SendMsg().SendText(key.ToString());
                            // 收到结束键，退出监听循环
                            break;
                        }
                    }

                    // 非阻塞延迟
                    await Task.Delay(50, ct);
                }

                // 如果是因为超时退出，可以做些处理（可选）
                if (!ct.IsCancellationRequested && !stopwatch.IsRunning)
                {
                    // Global.writeLog("键盘监听超时");
                }
            }
            catch (Exception ex)
            {
                // 记录日志
                // Logger.Error($"ListenLoop error: {ex.Message}");
            }
            finally
            {
                stopwatch.Stop();
            }
        }

        /// <summary>
        /// 停止监听并关闭硬件
        /// </summary>
        public void CloseKeyboard()
        {
            if (!_isListening)
            {
                return;
            }

            // 1. 停止后台监听任务
            _listenCts?.Cancel();
            try
            {
                _listenTask?.Wait(); // 等待监听任务结束
            }
            catch (AggregateException) { /* 忽略取消异常 */ }
            _listenCts?.Dispose();
            _listenCts = null;
            _listenTask = null;
            _isListening = false;

            // 2. 关闭键盘
            if (JustTideEPPDrv.DisableKeyboard() != 0)
            {
                Global.writeLog("关闭键盘失败");
            }
            else
            {
                Global.writeLog("关闭键盘成功");
            }

            // 3. 关闭串口
            if (JustTideEPPDrv.CloseCom() != 0)
            {
                Global.writeLog("关闭串口失败");
            }
            else
            {
                Global.writeLog("关闭串口成功");
            }
        }

        public void Dispose()
        {
            CloseKeyboard();
        }
    }

}
