using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;

namespace DeviceCommand.Device
{
    [BOBCommand]
    public class SQ0030G1D : Tcp
    {
        public SQ0030G1D(string ip, int port, int sendTimeout, int receiveTimeout)
        {
            ConfigureDevice(ip, port, sendTimeout, receiveTimeout);
        }
        #region 心跳
        private CancellationTokenSource _cancellationTokenSource;
        private Task? _heartbeatTask;
        private const int HeartbeatInterval = 3000;
        public bool IsActive = false;
        public int ReConnectionAttempts = 0;
        public const int MaxReconnectAttempts = 10;
        public override async Task<bool> ConnectAsync(CancellationToken ct = default)
        {
            await _commLock.WaitAsync(ct);
            try
            {
                if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
                if (TcpClient.Connected)
                {
                    return true;
                }
                await TcpClient.ConnectAsync(IPAddress, Port, ct);
                IsActive = true;
                StartHeartbeat();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
            finally
            {
                _commLock.Release();
            }
        }
        public override void Close()
        {
            if (!TcpClient.Connected)
            {
                throw new InvalidOperationException("TCP 没有连接成功");
            }
            if (TcpClient.Connected)
            {
                TcpClient.Close();
                StopHeartbeat();
            }
        }
        // 启动设备的心跳
        public void StartHeartbeat()
        {
            if (_heartbeatTask != null)
                return;
            if (_cancellationTokenSource == null || _cancellationTokenSource.IsCancellationRequested)
                _cancellationTokenSource = new();
            _heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
        }

        // 停止设备的心跳
        public void StopHeartbeat()
        {
            IsActive = false;
            _cancellationTokenSource.Cancel();
            _heartbeatTask = null;
        }

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

                try
                {
                    await 设置远程控制();
                }
                catch (Exception ex)
                {
                    IsActive = false;
                    ReConnectionAttempts++;
                    if (MaxReconnectAttempts < ReConnectionAttempts)
                    {
                        StopHeartbeat();
                        return;
                    }
                    await ReconnectDevice(ct);
                }
            }
        }
        private async Task ReconnectDevice(CancellationToken ct)
        {
            try
            {
                bool resultConnect = await ConnectAsync(ct);
                if (resultConnect)
                {
                    ReConnectionAttempts = 0;
                }
            }
            catch (Exception ex)
            {

            }
        }
        #endregion

        // ===================== 基础封装 =====================

        protected virtual Task 写命令(string cmd, CancellationToken ct = default)
            => SendAsync(cmd + "\n", ct);

        protected virtual async Task<string> 查询命令(string cmd, CancellationToken ct = default)
        {
            await SendAsync(cmd + "\n", ct);
            return await ReadAsync(ct: ct);
        }

        // ===================== 1. 基础控制 =====================

        public async Task 启动电源()
        {
            await 写命令($"OUTPut 1\n");
        }

        public async Task 关闭电源()
        {
            await 写命令($"OUTPut 0\n");
        }

        public virtual Task<string> 获取设备ID(CancellationToken ct = default)
            => 查询命令("*IDN?", ct);

        public virtual Task 重置设备(CancellationToken ct = default)
            => 写命令("*RST", ct);

        public virtual Task 设置远程控制(CancellationToken ct = default)
            => 写命令("SYST:REM", ct);

        public virtual Task 设置本地控制(CancellationToken ct = default)
            => 写命令("SYST:LOC", ct);

        public virtual Task 设置输出状态(bool on, CancellationToken ct = default)
            => 写命令($"OUTP:STAT {(on ? "ON" : "OFF")}", ct);

        public virtual async Task<bool> 获取输出状态(CancellationToken ct = default)
            => (await 查询命令("OUTP:STAT?", ct)).Trim().ToUpper() == "ON";

        // ===================== 2. 电压/频率控制 =====================

        public virtual Task 设置输出电压(double value, CancellationToken ct = default)
            => 写命令($"VOLT {value}", ct);

        public virtual async Task<double> 获取输出电压(CancellationToken ct = default)
            => double.Parse((await 查询命令("VOLT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture);

        public virtual async Task<double> 获取输出频率(CancellationToken ct = default)
            => double.Parse((await 查询命令("FREQ?", ct)).Replace("Hz", ""), CultureInfo.InvariantCulture);

        // ===================== 3. 保护 =====================

        public virtual Task 设置过压保护(double v, CancellationToken ct = default)
            => 写命令($"VOLT:PROT {v}", ct);

        public virtual async Task<double> 获取过压保护(CancellationToken ct = default)
            => double.Parse((await 查询命令("VOLT:PROT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture);

        public virtual Task 设置过流保护(double a, CancellationToken ct = default)
            => 写命令($"CURR:PROT {a}", ct);

        public virtual async Task<double> 获取过流保护(CancellationToken ct = default)
            => double.Parse((await 查询命令("CURR:PROT?", ct)).Replace("A", ""), CultureInfo.InvariantCulture);

        public virtual Task 清除保护(CancellationToken ct = default)
            => 写命令("SYST:PROT:CLE", ct);

        // ===================== 4. 测量 =====================

        public virtual async Task<double> 测量输出电压(CancellationToken ct = default)
            => double.Parse((await 查询命令("MEAS:VOLT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture);

        public virtual async Task<double> 测量输出电流(CancellationToken ct = default)
            => double.Parse((await 查询命令("MEAS:CURR?", ct)).Replace("A", ""), CultureInfo.InvariantCulture);

        public virtual async Task<double> 测量输出功率(CancellationToken ct = default)
            => double.Parse((await 查询命令("MEAS:POW?", ct)).Replace("W", ""), CultureInfo.InvariantCulture);

        public virtual async Task<(double volt, double curr, double pow)> 测量所有参数(CancellationToken ct = default)
        {
            var parts = (await 查询命令("MEAS:ARR?", ct)).Split(',');
            return (
                double.Parse(parts[0].Replace("V", ""), CultureInfo.InvariantCulture),
                double.Parse(parts[1].Replace("A", ""), CultureInfo.InvariantCulture),
                double.Parse(parts[2].Replace("W", ""), CultureInfo.InvariantCulture)
            );
        }

        // 切换到远程控制模式
        public virtual Task 设置远程控制模式(CancellationToken ct = default)
            => 写命令("SYST:REM", ct);

        // 切换到本地控制模式
        public virtual Task 设置本地控制模式(CancellationToken ct = default)
            => 写命令("SYST:LOC", ct);

        // 设定三相电压高低档
        public virtual Task 设置三相电压高低档(int range, CancellationToken ct = default)
            => 写命令($"OUTP:RANG {range}", ct); // 设定高低档：166（低档）/333（高档）

        // 设定通用输出电压
        public virtual Task 设置通用输出电压(double value, CancellationToken ct = default)
            => 写命令($"VOLT {value}", ct);

        // 设定三相输出电压
        public virtual Task 设置三相输出电压(double U, double V, double W, CancellationToken ct = default)
            => 写命令($"VOLT:PHAS A, {U}, B, {V}, C, {W}", ct);

        // 设定输出频率
        public virtual Task 设置输出频率(double freq, CancellationToken ct = default)
            => 写命令($"FREQ {freq}", ct);

        // 设定步阶输出电压
        public virtual Task 设置步阶输出电压(double targetVoltage, double stepTime, CancellationToken ct = default)
            => 写命令($"TRIG:TRAN:VOLT:STEP {targetVoltage}, {stepTime}", ct);

        // 设定步阶输出频率
        public virtual Task 设置步阶输出频率(double targetFrequency, double stepTime, CancellationToken ct = default)
            => 写命令($"TRIG:TRAN:FREQ:STEP {targetFrequency}, {stepTime}", ct);

        // 设定渐变输出电压
        public virtual Task 设置渐变输出电压(double startVoltage, double endVoltage, double sweepTime, CancellationToken ct = default)
            => 写命令($"TRIG:TRAN:VOLT:SWEEP {startVoltage}, {endVoltage}, {sweepTime}", ct);

        // 设定渐变输出频率
        public virtual Task 设置渐变输出频率(double startFreq, double endFreq, double sweepTime, CancellationToken ct = default)
            => 写命令($"TRIG:TRAN:FREQ:SWEEP {startFreq}, {endFreq}, {sweepTime}", ct);

        // 设定软件启动功能起始电压与额定电压
        public virtual Task 设置软件启动功能起始电压与额定电压(double startVoltage, double ratedVoltage, CancellationToken ct = default)
            => 写命令($"PON:VOLT {startVoltage}, {ratedVoltage}", ct);

        // 设定软件启动功能起始电压与起始频率
        public virtual Task 设置软件启动功能起始电压与起始频率(double startVoltage, double startFrequency, CancellationToken ct = default)
            => 写命令($"PON:FREQ {startVoltage}, {startFrequency}", ct);
    }
}
