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

namespace DeviceCommand.Device
{
    [BOBCommand]
    public class WS_68030_380T : ModbusTcp
    {
        public WS_68030_380T(string IpAddress, int port, int SendTimeout, int ReceiveTimeout)
        {
            ConfigureDevice(IpAddress, 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 WriteSingleRegisterAsync(1,0,1);
                }
                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

        private const byte SlaveAddress = 1;

       
        public virtual async Task 设置功率_KW(float 功率, CancellationToken ct = default)
        {
            var send = ConvertFromFloat(功率);
            await WriteMultipleRegistersAsync(1, 58, send).WaitAsync(ct);
        }

        public virtual async Task 加载(CancellationToken ct = default)
        {
            var tmp = new ushort();
            ushort send = (ushort)(tmp | (1 << 8));
            await WriteSingleRegisterAsync(1, 70, send).WaitAsync(ct);
        }

        public virtual async Task 卸载(CancellationToken ct = default)
        {
            await WriteSingleRegisterAsync(1, 70, new()).WaitAsync(ct);
        }

        public virtual async Task<float> 读取功率_KW(CancellationToken ct = default)
        {
            var re = await ReadHoldingRegistersAsync(1, 58, 2).WaitAsync(ct);
            return ConvertToFloat(re);
        }



        #region 辅助方法
        protected  float ConvertToFloat(ushort[] values)
        {
            byte[] bytes = new byte[4];
            bytes[3] = (byte)(values[0] >> 8);
            bytes[2] = (byte)(values[0] & 0xFF);
            bytes[1] = (byte)(values[1] >> 8);
            bytes[0] = (byte)(values[1] & 0xFF);
            return BitConverter.ToSingle(bytes, 0);
        }

        protected  ushort[] ConvertFromFloat(float value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            return new ushort[]
            {
                (ushort)((bytes[3] << 8) | bytes[2]),
                (ushort)((bytes[1] << 8) | bytes[0])
            };
        }
        #endregion
    }
}
