using LogClass;
using NModbus;
using System;
using System.Net.Sockets;

namespace CCDCount.DLL.Tools
{
    public class ModbusTcpClient
    {
        private TcpClient _tcpClient;
        private IModbusMaster _modbusMaster;

        public bool IsTcpClientConnected()
        {
            if (_tcpClient == null || _tcpClient.Client == null)
                return false;

            try
            {
                Socket socket = _tcpClient.Client;
                bool isReadable = socket.Poll(0, SelectMode.SelectRead);
                bool hasNoData = (socket.Available == 0);

                // 可读且无数据 = 连接已断开
                return !(isReadable && hasNoData);
            }
            catch (SocketException) { return false; }
            catch (ObjectDisposedException) { return false; }
        }

        /// <summary>
        /// 连接 Modbus TCP 服务器
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public bool Connect(string ipAddress, int port = 502)
        {
            try
            {
                _tcpClient = new TcpClient(ipAddress, port)
                {
                    SendTimeout = 2000,
                    ReceiveTimeout = 2000
                };
                // 使用 ModbusFactory 创建 Master（新版本 API）
                var factory = new ModbusFactory();
                _modbusMaster = factory.CreateMaster(_tcpClient);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"连接失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void Disconnect()
        {
            _modbusMaster?.Dispose();
            _tcpClient?.Close();
        }
        /// <summary>
        /// 读取线圈（功能码01）
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="startAddress"></param>
        /// <param name="numRegisters"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public bool[] ReadCoilsRegister(byte slaveId, ushort startAddress, ushort numRegisters)
        {
            if (_modbusMaster == null) throw new InvalidOperationException("未连接到服务器");
            try
            {
                return _modbusMaster.ReadCoils(slaveId, startAddress, numRegisters);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读取线圈失败: {ex.Message}");
                LOG.error($"MainThreadClass-ReadCoilsRegister-ReadCoilsRegister failed:{ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 读取保持寄存器（功能码03）
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="startAddress"></param>
        /// <param name="numRegisters"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public ushort[] ReadHoldingRegisters(byte slaveId, ushort startAddress, ushort numRegisters)
        {
            if (_modbusMaster == null) throw new InvalidOperationException("未连接到服务器");
            try
            {
                return _modbusMaster.ReadHoldingRegisters(slaveId, startAddress, numRegisters);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读取保持寄存器失败: {ex.Message}");
                LOG.error($"MainThreadClass-ReadHoldingRegisters-ReadHoldingRegisters failed:{ex.Message}");
                return null;
            }
        }
        /// <summary>
        /// 写入线圈（功能码05）
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="CoilsAddress"></param>
        /// <param name="values"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public void WriteCoilsRegister(byte slaveId, ushort CoilsAddress, bool values)
        {
            if (_modbusMaster == null) throw new InvalidOperationException("未连接到服务器");
            try
            {
                _modbusMaster.WriteSingleCoil(slaveId, CoilsAddress, values);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入线圈失败: {ex.Message}");
                LOG.error($"MainThreadClass-WriteCoilsRegister-WriteCoilsRegister failed:{ex.Message}");
            }
        }

        /// <summary>
        /// 写入单个寄存器（功能码06）
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="registerAddress"></param>
        /// <param name="value"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public void WriteSingleRegister(byte slaveId, ushort registerAddress, ushort value)
        {

            if (_modbusMaster == null) throw new InvalidOperationException("未连接到服务器");
            try
            {
                _modbusMaster.WriteSingleRegister(slaveId, registerAddress, value);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入单个寄存器失败: {ex.Message}");
                LOG.error($"MainThreadClass-WriteSingleRegister-WriteSingleRegister failed:{ex.Message}");
            }
        }

        /// <summary>
        /// 写入多个寄存器（功能码16）
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="startAddress"></param>
        /// <param name="values"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public void WriteMultipleRegisters(byte slaveId, ushort startAddress, ushort[] values)
        {
            if (_modbusMaster == null) throw new InvalidOperationException("未连接到服务器");
            try
            {
                _modbusMaster.WriteMultipleRegisters(slaveId, startAddress, values);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入多个寄存器失败: {ex.Message}");
                LOG.error($"MainThreadClass-WriteMultipleRegisters-WriteMultipleRegisters failed:{ex.Message}");
            }
        }
    }
}
