#ifndef MODBUS_TCP_CLIENT_H
#define MODBUS_TCP_CLIENT_H

#include <memory>
#include <string>
#include <vector>
#include <functional>
#include <mutex>
#include <atomic>

extern "C" {
#include "modbus.h"
}

/**
 * @brief Modbus TCP客户端类，基于libmodbus库实现
 * 
 * 提供完整的Modbus TCP客户端功能，包括：
 * - 连接管理
 * - 所有标准Modbus功能码支持
 * - 异步操作支持
 * - 错误处理和重连机制
 * - 数据类型转换
 */
class ModbusTCPClient {
public:
    // 连接状态枚举
    enum ConnectionState {
        DISCONNECTED = 0,   ///< 已断开连接
        CONNECTING,         ///< 正在连接
        CONNECTED,          ///< 已连接
        ERROR_STATE         ///< 错误状态
    };

    // 操作结果枚举
    enum Result {
        SUCCESS = 0,                ///< 操作成功
        ERROR_CONNECTION = -1,      ///< 连接错误
        ERROR_INVALID_PARAM = -2,   ///< 参数错误
        ERROR_TIMEOUT = -3,         ///< 超时错误
        ERROR_DEVICE = -4,          ///< 设备错误
        ERROR_PROTOCOL = -5,        ///< 协议错误
        ERROR_UNKNOWN = -6          ///< 未知错误
    };

    // 连接状态变化回调函数类型
    using ConnectionStateCallback = std::function<void(ConnectionState oldState, ConnectionState newState, const std::string& message)>;
    
    // 数据变化回调函数类型（用于监控数据变化）
    using DataChangeCallback = std::function<void(int address, const std::vector<uint16_t>& values)>;

public:
    /**
     * @brief 构造函数
     * @param serverIP 服务器IP地址
     * @param serverPort 服务器端口，默认502
     */
    ModbusTCPClient(const std::string& serverIP, int serverPort = 502);
    
    /**
     * @brief 析构函数
     */
    ~ModbusTCPClient();

    // 禁用拷贝构造和赋值
    ModbusTCPClient(const ModbusTCPClient&) = delete;
    ModbusTCPClient& operator=(const ModbusTCPClient&) = delete;

    /**
     * @brief 设置连接参数
     * @param serverIP 服务器IP地址
     * @param serverPort 服务器端口
     * @return 设置是否成功
     */
    bool SetConnectionParams(const std::string& serverIP, int serverPort);

    /**
     * @brief 设置从站ID
     * @param slaveId 从站ID (1-247)
     * @return 设置是否成功
     */
    bool SetSlaveId(int slaveId);

    /**
     * @brief 设置响应超时时间
     * @param timeoutMs 超时时间（毫秒）
     * @return 设置是否成功
     */
    bool SetTimeout(int timeoutMs);

    /**
     * @brief 设置连接状态变化回调
     * @param callback 回调函数
     */
    void SetConnectionStateCallback(ConnectionStateCallback callback);

    /**
     * @brief 连接到服务器
     * @return 连接结果
     */
    Result Connect();

    /**
     * @brief 断开连接
     */
    void Disconnect();

    /**
     * @brief 获取连接状态
     * @return 当前连接状态
     */
    ConnectionState GetConnectionState() const;

    /**
     * @brief 检查是否已连接
     * @return 是否已连接
     */
    bool IsConnected() const;

    // === 读操作 ===

    /**
     * @brief 读取线圈状态 (功能码0x01)
     * @param startAddress 起始地址
     * @param quantity 数量 (1-2000)
     * @param values 输出值数组
     * @return 操作结果
     */
    Result ReadCoils(int startAddress, int quantity, std::vector<bool>& values);

    /**
     * @brief 读取离散输入 (功能码0x02)
     * @param startAddress 起始地址
     * @param quantity 数量 (1-2000)
     * @param values 输出值数组
     * @return 操作结果
     */
    Result ReadDiscreteInputs(int startAddress, int quantity, std::vector<bool>& values);

    /**
     * @brief 读取保持寄存器 (功能码0x03)
     * @param startAddress 起始地址
     * @param quantity 数量 (1-125)
     * @param values 输出值数组
     * @return 操作结果
     */
    Result ReadHoldingRegisters(int startAddress, int quantity, std::vector<uint16_t>& values);

    /**
     * @brief 读取输入寄存器 (功能码0x04)
     * @param startAddress 起始地址
     * @param quantity 数量 (1-125)
     * @param values 输出值数组
     * @return 操作结果
     */
    Result ReadInputRegisters(int startAddress, int quantity, std::vector<uint16_t>& values);

    // === 写操作 ===

    /**
     * @brief 写单个线圈 (功能码0x05)
     * @param address 地址
     * @param value 值
     * @return 操作结果
     */
    Result WriteSingleCoil(int address, bool value);

    /**
     * @brief 写单个保持寄存器 (功能码0x06)
     * @param address 地址
     * @param value 值
     * @return 操作结果
     */
    Result WriteSingleRegister(int address, uint16_t value);

    /**
     * @brief 写多个线圈 (功能码0x0F)
     * @param startAddress 起始地址
     * @param values 值数组
     * @return 操作结果
     */
    Result WriteMultipleCoils(int startAddress, const std::vector<bool>& values);

    /**
     * @brief 写多个保持寄存器 (功能码0x10)
     * @param startAddress 起始地址
     * @param values 值数组
     * @return 操作结果
     */
    Result WriteMultipleRegisters(int startAddress, const std::vector<uint16_t>& values);

    // === 组合操作 ===

    /**
     * @brief 读写多个寄存器 (功能码0x17)
     * @param readStartAddress 读起始地址
     * @param readQuantity 读数量
     * @param writeStartAddress 写起始地址
     * @param writeValues 写值数组
     * @param readValues 读取的值数组（输出）
     * @return 操作结果
     */
    Result ReadWriteMultipleRegisters(int readStartAddress, int readQuantity,
                                      int writeStartAddress, const std::vector<uint16_t>& writeValues,
                                      std::vector<uint16_t>& readValues);

    // === 数据类型转换辅助函数 ===

    /**
     * @brief 将两个16位寄存器合并为32位整数
     * @param high 高位寄存器
     * @param low 低位寄存器
     * @return 32位整数值
     */
    static uint32_t RegistersToUInt32(uint16_t high, uint16_t low);

    /**
     * @brief 将32位整数分解为两个16位寄存器
     * @param value 32位整数值
     * @param high 高位寄存器（输出）
     * @param low 低位寄存器（输出）
     */
    static void UInt32ToRegisters(uint32_t value, uint16_t& high, uint16_t& low);

    /**
     * @brief 将两个16位寄存器合并为32位浮点数
     * @param high 高位寄存器
     * @param low 低位寄存器
     * @return 32位浮点数值
     */
    static float RegistersToFloat(uint16_t high, uint16_t low);

    /**
     * @brief 将32位浮点数分解为两个16位寄存器
     * @param value 32位浮点数值
     * @param high 高位寄存器（输出）
     * @param low 低位寄存器（输出）
     */
    static void FloatToRegisters(float value, uint16_t& high, uint16_t& low);

    // === 错误处理 ===

    /**
     * @brief 获取最后一次错误信息
     * @return 错误信息字符串
     */
    std::string GetLastError() const;

    /**
     * @brief 将Result转换为字符串
     * @param result 结果枚举
     * @return 结果描述字符串
     */
    static std::string ResultToString(Result result);

    /**
     * @brief 将ConnectionState转换为字符串
     * @param state 状态枚举
     * @return 状态描述字符串
     */
    static std::string ConnectionStateToString(ConnectionState state);

private:
    /**
     * @brief 设置连接状态
     * @param newState 新状态
     * @param message 状态变化消息
     */
    void SetConnectionState(ConnectionState newState, const std::string& message = "");

    /**
     * @brief 检查modbus上下文是否有效
     * @return 是否有效
     */
    bool IsModbusContextValid() const;

    /**
     * @brief 将libmodbus错误转换为Result
     * @return 转换后的结果
     */
    Result ConvertLibmodbusError() const;

    /**
     * @brief 设置最后错误信息
     * @param error 错误信息
     */
    void SetLastError(const std::string& error);

private:
    modbus_t* m_modbusContext;              ///< libmodbus上下文
    std::string m_serverIP;                 ///< 服务器IP地址
    int m_serverPort;                       ///< 服务器端口
    int m_slaveId;                          ///< 从站ID
    int m_timeoutMs;                        ///< 超时时间（毫秒）
    
    std::atomic<ConnectionState> m_connectionState;  ///< 连接状态
    ConnectionStateCallback m_stateCallback;        ///< 状态变化回调
    
    mutable std::mutex m_mutex;             ///< 互斥锁
    std::string m_lastError;                ///< 最后错误信息
};

#endif // MODBUS_TCP_CLIENT_H 