package com.jiayue.ipfcst.dataexchange.service;

import com.alibaba.fastjson.JSON;
import com.jiayue.ipfcst.common.data.constant.enums.TunnelStatus;
import com.jiayue.ipfcst.common.data.entity.ProtocolGatherDataPoint;
import com.jiayue.ipfcst.common.data.entity.gathertunnelinfo.FileParseTunnelInfo;
import com.jiayue.ipfcst.dataexchange.container.ProtocolDataContainer;
import com.jiayue.ipfcst.dataexchange.container.RecurringTaskContainer;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 负责处理文件解析传送过来的数据
 *
 * @author: xiuwei
 * @version:
 */
@Service
@Slf4j
public class FileParseTunnelService {


  public static final int ChannelStatusCheckInterval = 5;

  @Autowired
  TunnelInfoService tunnelInfoService;


  /**
   * 通道id ===》点位（通道顺序===》数据池id点位）
   */
  private Map<String, Map<Integer, ProtocolGatherDataPoint>> tunnelPoints = null;

  private Map<String, DateTime> flushTimeRecord = null;

  private Map<String, TunnelStatus> tunnelStatus = new HashMap<>();


  /**
   * 初始化
   */
  private void init() {
    this.tunnelPoints = new HashMap<>();
    this.flushTimeRecord = new HashMap<>();
    this.tunnelStatus = new HashMap<>();
    List<FileParseTunnelInfo> tunnels = tunnelInfoService.getAllFileParseTunnel();
    for (FileParseTunnelInfo tunnelInfo : tunnels) {
      if (!tunnelInfo.getIsEnable()) {
        continue;
      }
      Map<Integer, ProtocolGatherDataPoint> points = new HashMap<>();
      if (tunnelInfo.getDataPoints() != null && tunnelInfo.getDataPoints().size() != 0) {
        for (ProtocolGatherDataPoint point : tunnelInfo.getDataPoints()) {
          points.put(point.getProtocolPointNo(), point);
        }
      }
      this.tunnelPoints.put(tunnelInfo.getId(), points);
      this.flushTimeRecord.put(tunnelInfo.getId(), DateTime.now());
      this.tunnelStatus.put(tunnelInfo.getId(), TunnelStatus.CONNECTED);
    }
    RecurringTaskContainer.getInstance().addRecurringTask(ChannelStatusCheckInterval * 60, "反向隔离文件通道状态检测", () -> {
      Iterator<String> it = this.flushTimeRecord.keySet().iterator();
      String tunnelId;
      while (it.hasNext()) {
        tunnelId = it.next();
        //查看文件刷新时间是否在6分钟之内  应该是5分钟 以防刷新时间和检查时间重合 宽恕一分钟
        if (this.flushTimeRecord.get(tunnelId).isAfter(DateTime.now().minusMinutes(ChannelStatusCheckInterval + 1))) {
          if (!(TunnelStatus.CONNECTING == this.tunnelStatus.get(tunnelId))) {
            this.tunnelStatus.replace(tunnelId, TunnelStatus.CONNECTED);
          }
        } else {
          this.tunnelStatus.put(tunnelId, TunnelStatus.LOSECONN);
        }
      }
      return null;
    });

  }


  /**
   * 获取通道点位
   * 没有初始化时初始化
   *
   * @return 点位双map
   */
  private Map<String, Map<Integer, ProtocolGatherDataPoint>> getTunnelPoints() {
    if (this.tunnelPoints == null) {
      this.init();
    }
    return this.tunnelPoints;
  }

  /**
   * 重新构建点位
   */
  public synchronized void reBuildPoints() {
    init();
  }


  /**
   * 接收数据
   * list  仅接受 BigDecimal 和 boolean值 不接受其他类型值
   *
   * @param tunnelId 通道id
   * @param dates    数据
   */
  public synchronized void receiveData(String tunnelId, List dates) {
    log.info("接收到通道" + tunnelId + "传输的数据" + JSON.toJSONString(dates));
    if (getTunnelPoints().containsKey(tunnelId)) {
      Map<Integer, ProtocolGatherDataPoint> points = getTunnelPoints().get(tunnelId);
      this.flushTimeRecord.put(tunnelId, DateTime.now());
      for (int i = 0; i < dates.size(); i++) {
        if (points.containsKey(i)) {
          if (dates.get(i) instanceof BigDecimal) {
            ProtocolDataContainer.getInstance().putNumber(points.get(i).getId(), ((BigDecimal) dates.get(i)).multiply(BigDecimal.valueOf(points.get(i).getMagnification())));
          } else if (dates.get(i) instanceof Boolean) {
            ProtocolDataContainer.getInstance().putBoolean(points.get(i).getId(), (Boolean) dates.get(i));
          }
        }
      }
    } else {
      log.warn("文件解析通道无id为" + tunnelId + "的通道");
    }
  }

  public void receiveData(String tunnelId, List dates, Boolean status) {
    receiveData(tunnelId, dates);
    if (status != null) {
      log.info("生成隔离文件所需连接通道状态" + (status ? "正常" : "异常"));
      if (!status) {
        this.tunnelStatus.put(tunnelId, TunnelStatus.CONNECTING);
      }else{
        this.tunnelStatus.put(tunnelId, TunnelStatus.CONNECTED);
      }
    }
  }


  public Map<String, String> getFileParseTunnelStatus() {
    Map<String, String> tunnel = new HashMap<>();
    if (this.tunnelStatus != null) {
      this.tunnelStatus.forEach((k, v) -> {
        tunnel.put(k, TunnelStatus.CONNECTED.equals(v) ? "1" : "0");
      });
    }
    return tunnel;
  }


  public TunnelStatus getFileParseTunnelStatus(String tunnelId) {
    if (this.tunnelStatus.containsKey(tunnelId)) {
      return this.tunnelStatus.get(tunnelId);
    } else {
      return null;
    }
  }

  public void removeTunnel(String tunnelId) {
    this.tunnelPoints.remove(tunnelId);
    this.tunnelStatus.remove(tunnelId);
    this.flushTimeRecord.remove(tunnelId);
  }

}
