using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace DeviceCommand.Device
{
    [BOBCommand]
    public class IT6724CReverse : Serial_Port
    {
        public IT6724CReverse(string COMPort, int BaudRate, int DataBits, StopBits stopBits, Parity parity, int ReadTimeout, int ReceiveTimeout)
        {
            ConfigureDevice(COMPort, BaudRate, DataBits, stopBits, parity, ReadTimeout, 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 (SerialPort.IsOpen)
                    SerialPort.Close();

                SerialPort.PortName = PortName;
                SerialPort.BaudRate = BaudRate;
                SerialPort.DataBits = DataBits;
                SerialPort.StopBits = StopBits;
                SerialPort.Parity = Parity;
                SerialPort.ReadTimeout = ReadTimeout;
                SerialPort.WriteTimeout = WriteTimeout;
                if (SerialPort.IsOpen) return true;
                SerialPort.Open();
                IsActive = true;
                StartHeartbeat();

                return true;
            }
            finally
            {
                commLock.Release();
            }
        }
        public override void Close()
        {
            StopHeartbeat();
            if (SerialPort.IsOpen) SerialPort.Close();
        }

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

            _cancellationTokenSource?.Cancel();
            _cancellationTokenSource?.Dispose();

            _cancellationTokenSource = new CancellationTokenSource();

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

        public void StopHeartbeat()
        {
            try
            {
                IsActive = false;
                _cancellationTokenSource.Cancel();
                _heartbeatTask = null;
            }
            catch { }

            _heartbeatTask = null;
        }

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

                try
                {
                    await 设置为远程模式(ct);
                }
                catch (Exception ex)
                {
                    IsActive = false;
                    ReConnectionAttempts++;

                    if (ReConnectionAttempts > MaxReconnectAttempts)
                    {
                        LoggerHelper.InfoWithNotify("IT6724C重连多次失败");
                        StopHeartbeat();
                        return;
                    }

                    await ReconnectDevice(ct);
                }
            }
        }

        private async Task ReconnectDevice(CancellationToken ct)
        {
            try
            {
                bool ok = await ConnectAsync(ct);
                if (ok)
                    ReConnectionAttempts = 0;
            }
            catch { }
        }
        #endregion

        #region 设置命令

        public virtual async Task 清除输出保护(CancellationToken ct = default)
            =>await SendAsync("PROTection:CLEar\r\n", ct);

        public virtual async Task 设置电源输出(bool 开关, CancellationToken ct = default)
            =>await SendAsync($"OUTPut {(开关 ? 1 : 0)}\r\n", ct);

        public virtual async Task 设置为远程模式(CancellationToken ct = default)
            =>await SendAsync("SYSTem:REMote\r\n", ct);

        public virtual async Task 蜂鸣器测试(CancellationToken ct = default)
            =>await SendAsync("SYSTem:BEEPer\r\n", ct);

        public virtual async Task 设置电流(double 电流, CancellationToken ct = default)
            =>await SendAsync($"CURRent {电流}\r\n", ct);

        public virtual async Task 设置电流保护OCP电流(double 电流, CancellationToken ct = default)
            =>await SendAsync($"CURRent:PROTection {电流}\r\n", ct);

        public virtual async Task 设置OCP开关(bool 开关, CancellationToken ct = default)
            =>await SendAsync($"CURRent:PROTection:STATe {(开关 ? 1 : 0)}\r\n", ct);

        public virtual async Task 设置电压(double 电压, CancellationToken ct = default)
            =>await SendAsync($"VOLTage {电压}\r\n", ct);

        public virtual async Task 设置电压保护OVP电压(double 电压, CancellationToken ct = default)
            =>await SendAsync($"VOLT:PROTection {电压}\r\n", ct);

        public virtual async Task 设置OVP开关(bool 开关, CancellationToken ct = default)
            =>await SendAsync($"VOLT:PROTection:STATe {(开关 ? 1 : 0)}\r\n", ct);

        public virtual async Task 设置功率保护功率(double 电压, CancellationToken ct = default)
            =>await SendAsync($"POWer:PROTection {电压}\r\n", ct);

        public virtual async Task 设置功率保护开关(bool 开关, CancellationToken ct = default)
            =>await SendAsync($"POWer:PROTection:STATe {(开关 ? 1 : 0)}\r\n", ct);

        public virtual async Task 设置电流斜率(double 上升斜率, double 下降斜率, CancellationToken ct = default)
            =>await SendAsync($"CURRent:SLEW {上升斜率},{下降斜率}\r\n", ct);

        public virtual async Task 设置电压斜率(double 上升斜率, double 下降斜率, CancellationToken ct = default)
            =>await SendAsync($"VOLTage:SLEW {上升斜率},{下降斜率}\r\n", ct);

        public virtual async Task 发送自定义命令(string 指令, CancellationToken ct = default)
            =>await SendAsync($"{指令}\r\n", ct);
        public virtual async Task<string> 查询设备信息(CancellationToken ct = default)
        {
            await SendAsync("*IDN?\r\n", ct);
            return await ReadAsync(ct: ct);
        }
        /// <summary>
        /// 查询实际输出电流（单位：A）
        /// </summary>
        public virtual async Task<double> 查询实时电流(CancellationToken ct = default)
        {
            await SendAsync("MEASure:CURRent?\r\n", ct);
            var result = await ReadAsync(ct: ct);
            return Convert.ToDouble(result);
        }

        /// <summary>
        /// 查询实际输出电压（单位：V）
        /// </summary>
        public virtual async Task<double> 查询实时电压(CancellationToken ct = default)
        {
            await SendAsync("MEASure:VOLTage?\r\n", ct);
            var result = await ReadAsync(ct: ct);
            return Convert.ToDouble(result);
        }

        /// <summary>
        /// 查询实际输出功率（单位：W）
        /// </summary>
        public virtual async Task<double> 查询实时功率(CancellationToken ct = default)
        {
            await SendAsync("MEASure:POWer?\r\n", ct);
            var result = await ReadAsync(ct: ct);
            return Convert.ToDouble(result);
        }

        #endregion
    }
}
