package com.jiayue.ipfcst.dataexchange.service;

import com.jiayue.ipfcst.common.core.exception.BusinessException;
import com.jiayue.ipfcst.common.core.util.SpringContextHolder;
import com.jiayue.ipfcst.common.data.abst.equipmentinfo.AbstractEquipmentInfo;
import com.jiayue.ipfcst.common.data.constant.enums.EquipmentTypeEnum;
import com.jiayue.ipfcst.common.data.constant.enums.TunnelType;
import com.jiayue.ipfcst.common.data.entity.*;
import com.jiayue.ipfcst.dataexchange.container.DataPackerContainer;
import com.jiayue.ipfcst.dataexchange.container.ProtocolDataContainer;
import com.jiayue.ipfcst.dataexchange.container.ProtocolTunnelContainer;
import com.jiayue.ipfcst.dataexchange.dataprocesser.datapacker.AbstractDataPacker;
import com.jiayue.ipfcst.dataexchange.dataprocesser.datapacker.iml.EquipmentDataPacker;
import com.jiayue.ipfcst.dataexchange.dataprocesser.datapacker.iml.PowerStationDataPacker;
import com.jiayue.ipfcst.dataexchange.exception.DataExchangeException;
import com.jiayue.ipfcst.dataexchange.service.equipmentstatusdata.EquipmentInfoService;
import com.jiayue.ipfcst.dataexchange.tunnelworker.BaseProtocolTunnel;
import com.jiayue.ipfcst.dataexchange.tunnelworker.workassist.TunnelBuilder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 对集装箱操作的影响
 * 对容器内对象产生影响的操作
 * 这些操作主要来自页面的操作
 * 包括：对点表的操作  将会影响 通道池内的通道， 设备数据组装池里的组装器
 * 对通道信息的操作  将会影响通道池内的通道
 * （设备信息的修改将会影响入库时间）
 *
 * @author: xiuwei
 * @version: 3.0
 */
@Service
@Slf4j
public class ImpactOnContainerOperation {


  @Autowired
  ProtocolGatherDataPointService protocolGatherDataPointService;
  @Autowired
  ProtocolSenderDataPointService protocolSenderDataPointService;

  @Autowired
  FileParseTunnelService fileParseTunnelService;

  ProtocolTunnelContainer protocolTunnelContainer = ProtocolTunnelContainer.getInstance();

  @Autowired
  TunnelInfoService tunnelInfoService;

  @Autowired
  EquipmentInfoService equipmentInfoService;


  /**
   * 与采集点表相关的
   * 刷新所有的设备数据组装器点表
   * 刷新所有的通道点表
   */
  public void refreshAllDataPoint() {
    refreshAllGatherTunnelDataPoint();
    refreshAllEquipmentDataPoint();
  }


  /**
   * 更新所有采集通道的点位
   */
  public void refreshAllGatherTunnelDataPoint() {
    log.info("开始刷新所有的采集通道的点位");
    List<BaseTunnelInfo> tunnelInfos = tunnelInfoService.getAllGatherTunnel();
    for (BaseTunnelInfo baseTunnelInfo : tunnelInfos) {
      if (baseTunnelInfo.getIsEnable() && !TunnelType.FILEPARSE.equals(baseTunnelInfo.getTunnelType())) {
        tunnelReparseDataPoint(baseTunnelInfo);
      }
    }
    //除了协议通道的点位重新加载  文件通道的点位也重新加载
    fileParseTunnelService.reBuildPoints();
  }

  /**
   * 更新所有采集通道的点位
   */
  public void refreshAllSenderTunnelDataPoint() {
    log.info("开始刷新所有转发通道的点位");
    List<BaseTunnelInfo> tunnelInfos = tunnelInfoService.getAllSenderTunnel();
    for (BaseTunnelInfo baseTunnelInfo : tunnelInfos) {
      if (baseTunnelInfo.getIsEnable()) {
        tunnelReparseDataPoint(baseTunnelInfo);
      }
    }
  }


  /**
   * 更新所有设备的点位
   */
  public void refreshAllEquipmentDataPoint() {
    log.info("开始刷新所有的数据组装类");
    List<AbstractEquipmentInfo> abstractEquipmentInfos = equipmentInfoService.getAllEquipmentInfo();
    ProtocolDataContainer.getInstance().removeAllCalculatorTask();
    for (AbstractEquipmentInfo abstractEquipmentInfo : abstractEquipmentInfos) {
      equipmentDataPackerReparseDataPoint(abstractEquipmentInfo);
    }
    SpringContextHolder.getBean(PowerStationDataPacker.class).init();
  }

  /**
   * 容器内通道再次解析数据点
   * tunnelInfo 内须包含点位
   *
   * @param tunnelInfo 隧道信息
   */
  public void tunnelReparseDataPoint(BaseTunnelInfo tunnelInfo) {
    if (tunnelInfo.getTunnelType() == TunnelType.FILEPARSE) {
      return;
    }
    BaseProtocolTunnel protocolTunnel = protocolTunnelContainer.getTunnel(tunnelInfo.getId());
    if (protocolTunnel == null) {
      try {
        log.info("原通道池无该通道，创建新通道");
        TunnelBuilder.buildTunnel(tunnelInfo).startTunnel();
      } catch (DataExchangeException e) {
        log.error("创建新通道失败" + e);
      }
      return;
    }
    if ("in".equals(tunnelInfo.getTunnelType().getFlow())) {
      tunnelInfo.setDataPoints(protocolGatherDataPointService.getByTunnelId(tunnelInfo.getId()));
    } else {
      tunnelInfo.setDataPoints(protocolSenderDataPointService.getByTunnelId(tunnelInfo.getId()));
    }
    try {
      //重新获取当下该通道的点位
      protocolTunnel.refreshTunnelInfo(tunnelInfo).parseGatherDataPoint();
    } catch (DataExchangeException e) {
      e.printStackTrace();
    }
  }


  /**
   * 设备数据组装器重新解析数据点
   * 设备数据组装器再次解析数据点
   *
   * @param equipmentInfo 设备信息
   */
  public void equipmentDataPackerReparseDataPoint(AbstractEquipmentInfo equipmentInfo) {
    log.info("开始创建{}的数据包装类", equipmentInfo.getName());
    AbstractDataPacker equipmentDataPacker = DataPackerContainer.getInstance().getPacker(equipmentInfo.getEquipmentType().getMessage() + "-" + equipmentInfo.getId());
    List<ProtocolGatherDataPoint> dataPoints = protocolGatherDataPointService.getByEquipmentId(equipmentInfo.getId(), equipmentInfo.getEquipmentType());
    if (equipmentDataPacker == null && dataPoints.size()>0) {
      EquipmentDataPacker dataPacker = null;
      switch (equipmentInfo.getEquipmentType()) {
        case INVERTER:
          dataPacker = new EquipmentDataPacker(new InverterStatusData(), dataPoints);
          break;
        case WINDTOWER:
          dataPacker = new EquipmentDataPacker(new WindTowerStatusData(), dataPoints);
          break;
        case WINDTURBINE:
          dataPacker = new EquipmentDataPacker(new WindTurbineStatusData(), dataPoints);
          break;
        case WEATHERSTATION:
          dataPacker = new EquipmentDataPacker(new WeatherStationStatusData(), dataPoints);
          break;
        case AGC_AVC:
          dataPacker = new EquipmentDataPacker(new AGC_AVCStatusData(), dataPoints);
          break;
        default:
          return;
      }
      if (dataPacker != null && equipmentInfo.getInterval() != null && equipmentInfo.getInterval() > 2) {
        dataPacker.setInterval(equipmentInfo.getInterval());
      }
      DataPackerContainer.getInstance().addPacker(equipmentInfo.getEquipmentType().getMessage() + "-" + equipmentInfo.getId(), dataPacker);
    } else {
      if (dataPoints.size() > 0) {
        ((EquipmentDataPacker) equipmentDataPacker).parseGatherDataPoint(dataPoints);
      }
    }
  }


  /**
   * 当通道信息改变时 重新构建该通道
   *
   * @param tunnelInfo 通道信息
   */

  public void tunnelReBuild(BaseTunnelInfo tunnelInfo) throws BusinessException {
    if (TunnelType.FILEPARSE.equals(tunnelInfo.getTunnelType())) {
      fileParseTunnelService.reBuildPoints();
      return;
    }
    tunnelInfo = tunnelInfoService.getTunnelById(tunnelInfo.getId(), tunnelInfo.getTunnelType());
    if ("in".equals(tunnelInfo.getTunnelType().getFlow())) {
      tunnelInfo.setDataPoints(protocolGatherDataPointService.getByTunnelId(tunnelInfo.getId()));
    } else {
      tunnelInfo.setDataPoints(protocolSenderDataPointService.getByTunnelId(tunnelInfo.getId()));
    }
    BaseProtocolTunnel protocolTunnel = protocolTunnelContainer.getTunnel(tunnelInfo.getId());
    try {
      //停止通道链接  更新通道信息  构建通道  开启通道
      if (protocolTunnel == null) {
        log.info("原通道池内没有通道{}，创建并开启该通道", tunnelInfo.getTunnelName());
        TunnelBuilder.buildTunnel(tunnelInfo).startTunnel();
      } else {
        if (tunnelInfo.getIsEnable()) {
          log.info("重新加载通道{}配置", tunnelInfo.getTunnelName());
          protocolTunnel.tunnelStop().refreshTunnelInfo(tunnelInfo);
          Thread.sleep(1000);
          protocolTunnel.buildTunnel().startTunnel();
        } else {
          log.info("将通道{}关闭", tunnelInfo.getTunnelName());
          protocolTunnel.tunnelStop();
        }
      }
    } catch (DataExchangeException | InterruptedException e) {
      throw new BusinessException("通道重建异常");
    }

  }


  /**
   * 添加通道 新增通道
   *
   * @param tunnelInfo 通道信息
   */
  public void addTunnel(BaseTunnelInfo tunnelInfo) throws DataExchangeException {
    if (TunnelType.FILEPARSE.equals(tunnelInfo.getTunnelType())) {
      fileParseTunnelService.reBuildPoints();
    } else {
      BaseProtocolTunnel t;
      t = TunnelBuilder.buildTunnel(tunnelInfo);
      try {
        t.startTunnel();
      } catch (DataExchangeException e) {
        log.error("通道在启动时发生异常：" + e.getMsg());
      }
    }

  }


  /**
   * 从通道池内删除通道
   *
   * @param tunnelId 通道id
   */
  @SneakyThrows
  public void deleteTunnel(String tunnelId) {
    BaseProtocolTunnel tunnel = protocolTunnelContainer.getTunnel(tunnelId);
    if (tunnel != null) {
      tunnel.tunnelStop();
      protocolTunnelContainer.removeTunnel(tunnelId);
    } else {
      fileParseTunnelService.removeTunnel(tunnelId);
    }
  }


  /**
   * 电站更新信息
   */
  public void updatePowerStationInfo() {
    PowerStationDataPacker powerStationDataPacker = (PowerStationDataPacker) DataPackerContainer.getInstance().getPacker(EquipmentTypeEnum.POWERSTATION.getMessage());
    powerStationDataPacker.getElectricField();
  }

}
