using Common.Attributes;
using DeviceCommand.Base;
using Model.Models;
using System;
using System.ComponentModel;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;

namespace DeviceCommand.Devices
{
    [ADPCommand]
    public class N36600 : Tcp
    {
        private CancellationTokenSource? _heartbeatCts;
        private Task? _heartbeatTask;
        private const int HeartbeatInterval = 3000; // 心跳间隔 3 秒

        public bool IsActive { get; private set; } = false;
        public int ReConnectionAttempts { get; private set; } = 0;
        public const int MaxReconnectAttempts = 10;

        // 手册第 4 页明确规定：每条命令后面都要加结束符 0x0A (\n)
        private const string SCPIDelimiter = "\n";

        public N36600(TcpConfig config) : base(config)
        {
        }

        /// <summary>
        /// 建立 TCP 连接，成功后自动激活心跳
        /// </summary>
        public new async Task<bool> ConnectAsync(CancellationToken ct = default)
        {
            bool isConnected = await base.ConnectAsync(ct);
            if (isConnected)
            {
                IsActive = true;
                ReConnectionAttempts = 0;
                StartHeartbeat();
            }
            return isConnected;
        }

        public override void Close()
        {
            StopHeartbeat();
            base.Close();
        }

        #region 心跳与断线重连逻辑

        [Browsable(false)]
        public void StartHeartbeat()
        {
            if (_heartbeatTask != null && !_heartbeatTask.IsCompleted)
                return;

            _heartbeatCts?.Cancel();
            _heartbeatCts?.Dispose();
            _heartbeatCts = new CancellationTokenSource();

            _heartbeatTask = Task.Run(() => HeartbeatLoop(_heartbeatCts.Token));
        }

        [Browsable(false)]
        public void StopHeartbeat()
        {
            IsActive = false;
            if (_heartbeatCts != null && !_heartbeatCts.IsCancellationRequested)
            {
                _heartbeatCts.Cancel();
            }
            _heartbeatTask = null;
        }

        private async Task HeartbeatLoop(CancellationToken ct)
        {
            while (!ct.IsCancellationRequested)
            {
                try
                {
                    await Task.Delay(HeartbeatInterval, ct);
                    if (ct.IsCancellationRequested) break;

                    // 使用公共查询命令发送心跳，确保通道连接正常，且不破坏远程或本地锁定状态
                    await SendAsync($"*IDN?{SCPIDelimiter}", ct);
                    IsActive = true;
                    ReConnectionAttempts = 0;
                }
                catch (Exception)
                {
                    IsActive = false;
                    ReConnectionAttempts++;

                    if (ReConnectionAttempts > MaxReconnectAttempts)
                    {
                        StopHeartbeat();
                        base.Close();
                        return;
                    }

                    await ReconnectDeviceAsync(ct);
                }
            }
        }

        private async Task ReconnectDeviceAsync(CancellationToken ct)
        {
            try
            {
                await ConnectAsync(ct);
            }
            catch (Exception)
            {
                // 静默处理，等待下一轮心跳重试
            }
        }

        #endregion

        #region 3.1 IEEE 488.2 公用命令

        /// <summary>
        /// 3.1.1 读取电源的相关信息（制造商, 产品标号, 产品序列号, 软件版本号）
        /// </summary>
        public virtual async Task<string> 查询设备标识(CancellationToken ct = default)
        {
            return await WriteReadAsync($"*IDN?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        /// <summary>
        /// 3.1.2 从指定的单位中恢复 *SAV 命令保存的设定值 (参数：1~99)
        /// </summary>
        public virtual async Task 调用存储状态(int 组别, CancellationToken ct = default)
        {
            if (组别 < 1 || 组别 > 99) throw new ArgumentOutOfRangeException(nameof(组别), "组别有效范围为 1~99");
            await SendAsync($"*RCL {组别}{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.1.3 将仪器当前系统状态保存到非易失性内存中 (参数：1~99)
        /// </summary>
        public virtual async Task 保存当前状态(int 组别, CancellationToken ct = default)
        {
            if (组别 < 1 || 组别 > 99) throw new ArgumentOutOfRangeException(nameof(组别), "组别有效范围为 1~99");
            await SendAsync($"*SAV {组别}{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.1.4 远程控制触发一次
        /// </summary>
        public virtual async Task 远程触发(CancellationToken ct = default)
        {
            await SendAsync($"*TRG{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.1.5 返回状态、采集电压、采集电流 (格式: 状态码,电压值,电流值)
        /// </summary>
        public virtual async Task<string> 查询全部状态及采样(CancellationToken ct = default)
        {
            return await WriteReadAsync($"*ALL?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        #endregion

        #region 3.2 APPLy 命令子系统

        /// <summary>
        /// 3.2.1 设置输出电压和输出电流值
        /// </summary>
        public virtual async Task 快捷设置电压电流(double 电压, double 电流, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，规范应用 APPL 短格式
            string cmd = string.Format(CultureInfo.InvariantCulture, "APPL {0:F3},{1:F3}{2}", 电压, 电流, SCPIDelimiter);
            await SendAsync(cmd, ct);
        }

        /// <summary>
        /// 3.2.1 查询当前设定的输出电压和电流值
        /// </summary>
        public virtual async Task<string> 查询快捷电压电流设定(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            return await WriteReadAsync($"APPL?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        #endregion

        #region 3.5 MEASure 命令子系统

        /// <summary>
        /// 3.5.1 查询通道输出端子上测得的直流电流值 (A)
        /// </summary>
        [Monitorable("低压直流电源电流")]
        public virtual async Task<string> 查询实际电流(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，改用标准 MEAS:CURR?
            return await WriteReadAsync($"MEAS:CURR?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        /// <summary>
        /// 3.5.2 查询通道输出端子上测得的直流功率值 (W)
        /// </summary>
        [Monitorable("低压直流电源功率")]
        public virtual async Task<string> 查询实际功率(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，改用标准 MEAS:POW?
            return await WriteReadAsync($"MEAS:POW?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        /// <summary>
        /// 3.5.3 查询通道输出端子上测得的直流电压值 (V)
        /// </summary>
        [Monitorable("低压直流电源电压")]
        public virtual async Task<string> 查询实际电压(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，改用标准 MEAS:VOLT?
            return await WriteReadAsync($"MEAS:VOLT?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        /// <summary>
        /// 3.5.4 查询通道输出端子上测得的电压、电流和功率的组合值
        /// </summary>
        public virtual async Task<string> 查询电压电流功率数组(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            return await WriteReadAsync($"MEAS:VAP?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        
        /// <summary>
        /// 3.5.5 查询通道输出端子上测得的输出时间长度
        /// </summary>
        public virtual async Task<string> 查询总输出时间长度(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            return await WriteReadAsync($"MEAS:TIME:OUTP?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        #endregion

        #region 3.6 OUTPut 命令子系统

        /// <summary>
        /// 3.6.1 设置电源输出开关
        /// </summary>
        public virtual async Task 设置DC输出(bool 开启, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，改用 OUTP 短格式
            string 状态 = 开启 ? "ON" : "OFF";
            await SendAsync($"OUTP {状态}{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.6.1 查询通道输出状态 (返回 ON 或 OFF)
        /// </summary>
        public virtual async Task<string> 查询DC输出状态(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            return await WriteReadAsync($"OUTP?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        /// <summary>
        /// 3.6.2 控制电源输出定时器的开关状态
        /// </summary>
        public virtual async Task 设置定时器状态(bool 开启, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            string 状态 = 开启 ? "ON" : "OFF";
            await SendAsync($"OUTP:TIME {状态}{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.6.3 设定电源输出定时器的时间 (单位: s, 范围: 0.1 ~ 999999.9)
        /// </summary>
        public virtual async Task 设置定时器时间(double 秒数, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            string cmd = string.Format(CultureInfo.InvariantCulture, "OUTP:TIME:DATA {0:F1}{1}", 秒数, SCPIDelimiter);
            await SendAsync(cmd, ct);
        }

        /// <summary>
        /// 3.6.4 设定电源输出的模式优先权 (CV优先 或 CC优先)
        /// </summary>
        public virtual async Task 设置输出模式优先(bool 是CV优先, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            string 模式 = 是CV优先 ? "CV" : "CC";
            await SendAsync($"OUTP:MODE {模式}{SCPIDelimiter}", ct);
        }

        #endregion

        #region 3.7 SOURce 命令子系统

        /// <summary>
        /// 3.7.1.1 清除输出电流保护(OCP)电路状态
        /// </summary>
        public virtual async Task 清除电流保护状态(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            await SendAsync($"CURR:PROT:CLE{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.7.1.2 使能或禁止当前输出电流保护(OCP)电路
        /// </summary>
        public virtual async Task 设置电流保护使能(bool 启用, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，将 STATE 改为更常用的 STAT 简写
            string 状态 = 启用 ? "ON" : "OFF";
            await SendAsync($"CURR:PROT:STAT {状态}{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.7.1.4 设置输出电流保护(OCP)阀值 (A)
        /// </summary>
        public virtual async Task 设置过流保护值(double 电流, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号。按 NGI 通用指令树，加上层级限制或者直接作用于 CURR:PROT
            string cmd = string.Format(CultureInfo.InvariantCulture, "CURR:PROT {0:F3}{1}", 电流, SCPIDelimiter);
            await SendAsync(cmd, ct);
        }

        /// <summary>
        /// 3.7.1.7 设置电源的输出电流值 (A)
        /// </summary>
        public virtual async Task 设置电流(double 电流, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，改用标准 CURR 短格式
            string cmd = string.Format(CultureInfo.InvariantCulture, "CURR {0:F3}{1}", 电流, SCPIDelimiter);
            await SendAsync(cmd, ct);
        }

        /// <summary>
        /// 3.7.2.1 清除输出电压保护(OVP)电路状态
        /// </summary>
        public virtual async Task 清除电压保护状态(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            await SendAsync($"VOLT:PROT:CLE{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.7.2.2 使能或禁止当前输出电压保护(OVP)电路
        /// </summary>
        public virtual async Task 设置电压保护使能(bool 启用, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            string 状态 = 启用 ? "ON" : "OFF";
            await SendAsync($"VOLT:PROT:STAT {状态}{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.7.2.4 设置输出电压保护(OVP)阀值 (V)
        /// </summary>
        public virtual async Task 设置过压保护值(double 电压, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            string cmd = string.Format(CultureInfo.InvariantCulture, "VOLT:PROT {0:F3}{1}", 电压, SCPIDelimiter);
            await SendAsync(cmd, ct);
        }

        /// <summary>
        /// 3.7.2.7 设置电源的输出电压值 (V)
        /// </summary>
        public virtual async Task 设置电压(double 电压, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，改用标准 VOLT 短格式
            string cmd = string.Format(CultureInfo.InvariantCulture, "VOLT {0:F3}{1}", 电压, SCPIDelimiter);
            await SendAsync(cmd, ct);
        }

        /// <summary>
        /// 3.7.2.8 设定电压输出范围的上限电压值 (V)
        /// </summary>
        public virtual async Task 设置电压上限限制(double 电压, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            string cmd = string.Format(CultureInfo.InvariantCulture, "VOLT:LIM {0:F3}{1}", 电压, SCPIDelimiter);
            await SendAsync(cmd, ct);
        }
        /// <summary>
        /// 3.7.2.9 清除电压上限限制（恢复为设备物理允许的最大电压值）
        /// </summary>
        public virtual async Task 清除电压上限限制(CancellationToken ct = default)
        {
            // 发送 MAXimum 设为最大值以达到“清除限制”的效果
            await SendAsync($"VOLT:LIMIT MAX{SCPIDelimiter}", ct); // 对应手册 3.7.2.8
        }
        /// <summary>
        /// 3.7.3.1 设置输出功率值 (W)
        /// </summary>
        public virtual async Task 设置功率(double 功率, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号，改用标准 POW 短格式
            string cmd = string.Format(CultureInfo.InvariantCulture, "POW {0:F3}{1}", 功率, SCPIDelimiter);
            await SendAsync(cmd, ct);
        }

        /// <summary>
        /// 3.7.3.2 禁止或使能当前恒功率(CP)输出
        /// </summary>
        public virtual async Task 设置恒功率输出使能(bool 启用, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            string 状态 = 启用 ? "ON" : "OFF";
            await SendAsync($"POW:STAT {状态}{SCPIDelimiter}", ct);
        }

        #endregion

        #region 3.9 SYSTem 命令子系统

        /// <summary>
        /// 3.9.1 控制蜂鸣器开关
        /// </summary>
        public virtual async Task 设置蜂鸣器状态(bool 开启, CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            string 状态 = 开启 ? "ON" : "OFF";
            await SendAsync($"SYST:BEEP:STAT {状态}{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.9.2 使蜂鸣器强制鸣叫一声
        /// </summary>
        public virtual async Task 蜂鸣器鸣叫(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            await SendAsync($"SYST:BEEP{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.9.4 查询仪器当前出错记录数量 (最大 18 组)
        /// </summary>
        public virtual async Task<string> 查询错误记录数量(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            return await WriteReadAsync($"SYST:ERR:COUN?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        /// <summary>
        /// 3.9.5 读取仪器的出错信息 (成功返回 0,"No error")
        /// </summary>
        public virtual async Task<string> 查询错误信息(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            return await WriteReadAsync($"SYST:ERR?{SCPIDelimiter}", SCPIDelimiter, ct);
        }

        /// <summary>
        /// 3.9.7 设置电源为面板控制模式 (本地 Local 状态，前面板按键可用)
        /// </summary>
        public virtual async Task 切换本地控制模式(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            await SendAsync($"SYST:LOC{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.9.8 设置电源为远程控制模式 (Remote 状态)
        /// </summary>
        public virtual async Task 切换远程控制模式(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            await SendAsync($"SYST:REM{SCPIDelimiter}", ct);
        }

        /// <summary>
        /// 3.9.9 通过通信接口设置电源为远程控制锁定模式
        /// </summary>
        public virtual async Task 远程控制模式锁定(CancellationToken ct = default)
        {
            // 修正：去除前缀冒号
            await SendAsync($"SYST:RWL{SCPIDelimiter}", ct);
        }

        #endregion
    }
}