package com.xzzn.common.core.modbus;

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.ip.IpParameters;
import com.xzzn.common.core.modbus.domain.DeviceConfig;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Modbus连接管理器
 * 使用长连接模式，维护连接缓存，复用已有连接
 */
@Component
public class Modbus4jConnectionManager {
    private static final Logger logger = LoggerFactory.getLogger(Modbus4jConnectionManager.class);

    private final ModbusFactory modbusFactory = new ModbusFactory();
    
    private final Map<String, ModbusMaster> connectionCache = new ConcurrentHashMap<>();

    /**
     * 获取或创建连接（长连接模式）
     */
    public ModbusMaster borrowMaster(DeviceConfig config) throws Exception {
        String key = buildConnectionKey(config);
        ModbusMaster master = connectionCache.get(key);
        
        if (master == null) {
            synchronized (this) {
                master = connectionCache.get(key);
                if (master == null) {
                    master = createNewConnection(config);
                    connectionCache.put(key, master);
                    logger.info("创建新Modbus长连接: {}:{}", config.getHost(), config.getPort());
                }
            }
        }

        
        return master;
    }

    /**
     * 归还连接（长连接模式，不关闭）
     */
    public void returnMaster(DeviceConfig config, ModbusMaster master) {
    }

    /**
     * 废弃连接（发生异常时关闭并移除）
     */
    public void invalidateMaster(DeviceConfig config, ModbusMaster master) {
        String key = buildConnectionKey(config);
        connectionCache.remove(key);
        destroyMaster(master, config);
        logger.warn("废弃并移除Modbus连接: {}:{}", config.getHost(), config.getPort());
    }

    private ModbusMaster createNewConnection(DeviceConfig config) throws Exception {
        IpParameters params = new IpParameters();
        params.setHost(config.getHost());
        params.setPort(config.getPort());
        params.setEncapsulated(false);
        
        ModbusMaster master = modbusFactory.createTcpMaster(params, true);
        master.init();

        return master;
    }

    private void destroyMaster(ModbusMaster master, DeviceConfig config) {
        if (master != null) {
            try {
                master.destroy();
                logger.debug("已关闭Modbus连接: {}:{}", config.getHost(), config.getPort());
            } catch (Exception e) {
                logger.warn("关闭Modbus连接异常: {}:{}", config.getHost(), config.getPort(), e);
            }
        }
    }

    private String buildConnectionKey(DeviceConfig config) {
        return config.getHost() + ":" + config.getPort();
    }

    /**
     * 关闭所有连接
     */
    public void closeAllConnections() {
        for (Map.Entry<String, ModbusMaster> entry : connectionCache.entrySet()) {
            try {
                if (entry.getValue() != null) {
                    entry.getValue().destroy();
                }
            } catch (Exception e) {
                logger.warn("关闭Modbus连接异常: {}", entry.getKey(), e);
            }
        }
        connectionCache.clear();
        logger.info("已关闭所有Modbus连接");
    }

}
