package com.jiayue.ipfcst.dataexchange.tunnelworker.gathers.iml;

import com.jiayue.ipfcst.common.data.constant.enums.TunnelStatus;
import com.jiayue.ipfcst.common.data.entity.gathertunnelinfo.GatherModbusRtuWithTcpServerTunnelInfo;
import com.jiayue.ipfcst.common.data.entity.gathertunnelinfo.GatherModbusTcpTunnelInfo;
import com.jiayue.ipfcst.dataexchange.exception.DataExchangeException;
import com.jiayue.ipfcst.dataexchange.tunnelworker.BaseProtocolTunnel;
import com.jiayue.ipfcst.dataexchange.tunnelworker.workassist.SingleThreadPoolExecutorUtil;
import wei.yigulu.modbus.domain.FunctionCode;
import wei.yigulu.modbus.netty.HSModbusTcpMasterBuilder;
import wei.yigulu.modbus.netty.ModbusRtuMasterWithTcpServer;

import java.net.InetSocketAddress;

/**
 * modbus协议TCP数据采集
 *
 * @author 修唯xiuwei
 * @version 3.0
 */

public class ModbusRtuMasterWithTcpServerDataGather extends AbstractModbusDataGather<GatherModbusRtuWithTcpServerTunnelInfo, ModbusRtuMasterWithTcpServerDataGather.MyModbusMaster> {



  /**
   * 构造方法
   *
   * @param gatherModbusRtuWithTcpServerTunnelInfo 通道信息
   */
  public ModbusRtuMasterWithTcpServerDataGather(GatherModbusRtuWithTcpServerTunnelInfo gatherModbusRtuWithTcpServerTunnelInfo) {
    super(gatherModbusRtuWithTcpServerTunnelInfo);
  }

  @Override
  public ModbusRtuMasterWithTcpServerDataGather buildTunnel() throws DataExchangeException {
    protocolBuilder = new MyModbusMaster(tunnelInfo.getSelfPort());
    protocolBuilder.setIp(tunnelInfo.getSelfIp());
    protocolBuilder.setLog(this.log);
    setSlaveId(this.tunnelInfo.getSlaveId());
    setFunctionCode(FunctionCode.valueOf(this.tunnelInfo.getFunctionCode()));
    this.parseGatherDataPoint();
    this.setTunnelStatus(TunnelStatus.BUILT);
    protocolTunnelContainer.addTunnel(this);
    log.info("成功创建ModbusTcpMaster通道对象：{}", this.tunnelInfo.getTunnelName());
    return this;
  }

  @Override
  public void getDataFromProtocol() throws DataExchangeException {
    try {
      super.getDataFromProtocol();
      this.consecutiveExceptions=0;
      this.setTunnelStatus(TunnelStatus.LISTENPORTSUCCESSANDCONN);
    }catch (Exception e){
      this.consecutiveExceptions++;
      if(consecutiveExceptions>10) {
        this.setTunnelStatus(TunnelStatus.LISTENPORTSUCCESSANDCONNANDCOMMERROR);
      }
    }
  }

  @Override
  public ModbusRtuMasterWithTcpServerDataGather startTunnel() throws DataExchangeException {
    log.info("modbus TCP Master {} 通道开始连接", getTunnelInfo().getTunnelName());
    protocolTunnelContainer.addSaveSendDataTask(this);
    protocolTunnelContainer.addUpdateDateTask(this);
    try {
      SingleThreadPoolExecutorUtil.executeBySingleThreadExecutor(() -> {
        try {
          this.protocolBuilder.create();
          log.error("Modbus TCP Master  通道监听结束");
        } catch (Exception e) {
          log.error("Modbus TCP Master  创建通道失败", e);
          setTunnelStatus(TunnelStatus.LISTENPORTFAIL);
        }
      });
    } catch (Exception e) {
      log.error("Modbus TCP Master 创建通道失败", e);
      setTunnelStatus(TunnelStatus.LISTENPORTFAIL);
      throw new DataExchangeException(10007, "Modbus TCP Master创建通道失败");
    }
    if (TunnelStatus.LISTENPORTFAIL != getTunnelStatus()) {
      setTunnelStatus(TunnelStatus.LISTENPORTSUCCESS);
    }
    return this;
  }

  @Override
  public BaseProtocolTunnel tunnelStop() throws DataExchangeException {
    if (this.protocolBuilder != null) {
      this.protocolBuilder.stop();
    }
    log.info("关闭 modbus TCP master 通道 {}", this.tunnelInfo.getTunnelName());
    return super.tunnelStop();
  }


  class MyModbusMaster  extends ModbusRtuMasterWithTcpServer{

    public MyModbusMaster(int port) {
      super(port);
    }

    @Override
    public void connected(InetSocketAddress ipSocket) {
      setTunnelStatus(TunnelStatus.LISTENPORTSUCCESSANDCONN);
    }

    @Override
    public void disconnected(InetSocketAddress ipSocket) {

      if(this.getChannels().size()==0)
        //当没有连接联入监听端口时  设置该状态
      setTunnelStatus(TunnelStatus.LISTENPORTSUCCESSANDNOCONN);
    }

  }


}
