using System;
using XP.Hardware.RaySource.Comet;
using XP.Hardware.RaySource.Comet.Messages.Commands;
using XP.Hardware.RaySource.Comet.Messages.Responses;

namespace XP.Hardware.RaySource.Comet.Host.Pipe
{
    /// <summary>
    /// 命令分发器
    /// 根据命令类型分发到 CometPviClient 对应方法
    /// </summary>
    static class CommandDispatcher
    {
        /// <summary>
        /// 退出标志，DisconnectCommand 处理后设置为 true
        /// </summary>
        public static bool ShouldExit { get; private set; }

        /// <summary>
        /// 分发命令到 CometPviClient 对应方法
        /// </summary>
        /// <param name="command">待处理的命令</param>
        /// <returns>处理结果响应</returns>
        public static RaySourceResponse Dispatch(RaySourceCommand command)
        {
            try
            {
                switch (command.CommandType)
                {
                    case "Initialize":
                        return HandleInitialize((InitializeCommand)command);
                    case "ConnectVariables":
                        return HandleConnectVariables();
                    case "TurnOn":
                        return HandleTurnOn();
                    case "TurnOff":
                        return HandleTurnOff();
                    case "SetVoltage":
                        return HandleSetVoltage((SetVoltageCommand)command);
                    case "SetCurrent":
                        return HandleSetCurrent((SetCurrentCommand)command);
                    case "ReadVoltage":
                        return HandleReadVoltage();
                    case "ReadCurrent":
                        return HandleReadCurrent();
                    case "ReadSystemStatus":
                        return HandleReadSystemStatus();
                    case "ReadErrors":
                        return HandleReadErrors();
                    case "Disconnect":
                        return HandleDisconnect();
                    case "TxiOn":
                        return HandleTxiOn();
                    case "TxiOff":
                        return HandleTxiOff();
                    case "WarmUp":
                        return HandleWarmUp();
                    case "Training":
                        return HandleTraining();
                    case "FilamentCalibration":
                        return HandleFilamentCalibration();
                    case "AutoCenter":
                        return HandleAutoCenter();
                    case "SetPowerMode":
                        return HandleSetPowerMode((SetPowerModeCommand)command);
                    default:
                        return new OperationResponse
                        {
                            Success = false,
                            ErrorMessage = $"未知的命令类型：{command.CommandType}"
                        };
                }
            }
            catch (Exception ex)
            {
                return new OperationResponse
                {
                    Success = false,
                    ErrorMessage = $"命令处理异常：{ex.Message}"
                };
            }
        }


        /// <summary>
        /// 等待 PVI 回调链完成的超时时间（毫秒）
        /// PVI Service.Connect() → Service_Connected → CPU.Connect() → Cpu_Connected 整个链路需要时间
        /// </summary>
        private const int PviConnectTimeoutMs = 30000;

        private static RaySourceResponse HandleInitialize(InitializeCommand cmd)
        {
            // PVI 回调链依赖 WinForms 消息泵派发事件
            // 不能用 ManualResetEventSlim.Wait() 阻塞 UI 线程，否则回调无法触发
            // 改用带消息泵的轮询等待，保持 Application.DoEvents() 运转
            bool completed = false;
            bool errorOccurred = false;
            string errorMessage = null;

            // 订阅连接状态变更事件
            EventHandler<PviConnectionState> stateHandler = (sender, state) =>
            {
                if (state == PviConnectionState.ServiceConnected)
                {
                    Console.Error.WriteLine("[Host] PVI 回调链完成，ServiceConnected");
                    completed = true;
                }
            };

            // 订阅错误事件（PVI 连接可能失败）
            EventHandler<string> errorHandler = (sender, msg) =>
            {
                errorOccurred = true;
                errorMessage = msg;
                Console.Error.WriteLine($"[Host] PVI 连接错误：{msg}");
                completed = true;
            };

            CometPviClient.ConnectionStateChanged += stateHandler;
            CometPviClient.ErrorOccurred += errorHandler;

            try
            {
                CometPviClient.Initialize(cmd.IpAddress, cmd.Port, cmd.CpuName, cmd.SourcePort, cmd.StationNumber);

                // 带消息泵的等待循环，保持 UI 消息派发，让 PVI 回调能触发
                var deadline = DateTime.UtcNow.AddMilliseconds(PviConnectTimeoutMs);
                while (!completed && DateTime.UtcNow < deadline)
                {
                    System.Windows.Forms.Application.DoEvents();
                    System.Threading.Thread.Sleep(50);
                }

                if (!completed)
                {
                    return new OperationResponse
                    {
                        Success = false,
                        ErrorMessage = "PVI 连接超时，回调链未在规定时间内完成"
                    };
                }

                if (errorOccurred)
                {
                    return new OperationResponse
                    {
                        Success = false,
                        ErrorMessage = $"PVI 连接失败：{errorMessage}"
                    };
                }

                return new OperationResponse { Success = true };
            }
            finally
            {
                CometPviClient.ConnectionStateChanged -= stateHandler;
                CometPviClient.ErrorOccurred -= errorHandler;
            }
        }


        private static RaySourceResponse HandleConnectVariables()
        {
            CometPviClient.ConnectVariables();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleTurnOn()
        {
            CometPviClient.TurnOn();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleTurnOff()
        {
            CometPviClient.TurnOff();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleSetVoltage(SetVoltageCommand cmd)
        {
            CometPviClient.SetVoltage(cmd.Voltage);
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleSetCurrent(SetCurrentCommand cmd)
        {
            CometPviClient.SetCurrent(cmd.Current);
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleReadVoltage()
        {
            var voltage = CometPviClient.ReadVoltage();
            return new OperationResponse { Success = true, Data = voltage };
        }

        private static RaySourceResponse HandleReadCurrent()
        {
            var current = CometPviClient.ReadCurrent();
            return new OperationResponse { Success = true, Data = current };
        }

        private static RaySourceResponse HandleReadSystemStatus()
        {
            var status = CometPviClient.ReadSystemStatus();
            return new StatusResponse
            {
                Success = true,
                SetVoltage = status.SetVoltage,
                ActualVoltage = status.ActualVoltage,
                SetCurrent = status.SetCurrent,
                ActualCurrent = status.ActualCurrent,
                IsXRayOn = status.IsXRayOn,
                WarmUpStatus = status.WarmUpStatus,
                VacuumStatus = status.VacuumStatus,
                StartUpStatus = status.StartUpStatus,
                AutoCenterStatus = status.AutoCenterStatus,
                FilamentAdjustStatus = status.FilamentAdjustStatus,
                IsInterlockActive = status.IsInterlockActive,
                WatchdogStatus = status.WatchdogStatus,
                PowerMode = status.PowerMode,
                TxiStatus = status.TxiStatus
            };
        }

        private static RaySourceResponse HandleReadErrors()
        {
            var errors = CometPviClient.ReadErrors();
            return new ErrorDataResponse
            {
                Success = true,
                SystemError = errors.SystemError,
                HSGError = errors.HSGError,
                TubeError = errors.TubeError,
                TubeVacError = errors.TubeVacError
            };
        }

        private static RaySourceResponse HandleDisconnect()
        {
            CometPviClient.Disconnect();
            ShouldExit = true;
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleTxiOn()
        {
            CometPviClient.TxiOn();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleTxiOff()
        {
            CometPviClient.TxiOff();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleWarmUp()
        {
            CometPviClient.WarmUp();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleTraining()
        {
            CometPviClient.Training();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleFilamentCalibration()
        {
            CometPviClient.FilamentCalibration();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleAutoCenter()
        {
            CometPviClient.AutoCenter();
            return new OperationResponse { Success = true };
        }

        private static RaySourceResponse HandleSetPowerMode(SetPowerModeCommand cmd)
        {
            CometPviClient.SetPowerMode(cmd.Mode);
            return new OperationResponse { Success = true };
        }
    }
}