package com.jiayue.ipfcst.dataexchange.service.equipmentstatusdata;

import com.jiayue.ipfcst.common.data.constant.enums.AbnormalCode;
import com.jiayue.ipfcst.common.data.constant.enums.EquipmentTypeEnum;
import com.jiayue.ipfcst.common.data.entity.ProtocolGatherDataPoint;
import com.jiayue.ipfcst.common.data.entity.WindTowerStatusData;
import com.jiayue.ipfcst.common.data.repository.WindTowerStatusDataRepository;
import com.jiayue.ipfcst.console.service.SysParameterService;
import com.jiayue.ipfcst.dataexchange.service.ProtocolGatherDataPointService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.annotation.Transient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 测风塔状态数据
 *
 * @author: xiuwei
 * @version:
 */
@Service
@Slf4j
public class WindTowerStatusDataService {

  /**
   * 死值检查
   */
  private final Map<Integer, DeadValueChecker> deadValueCheckers = new HashMap<>();

  /**
   * 测风塔异常状态值
   */
  private final Map<Integer, AbnormalCode> abnormalSignMap = new HashMap<>();

  private final SysParameterService sysParameterService;


  private final List<String> layerConcerned;


  public List<String> getLayerConcerned() {
    return this.layerConcerned;
  }

  private static final String LAYER_CONCERNED = "layerConcerned";

  private static final String LAYER_CONCERNED_DEFAULT = "10,30,50,70,90,HUB";

  final WindTowerStatusDataRepository windTowerStatusDataRepository;

  final ProtocolGatherDataPointService protocolGatherDataPointService;

  public WindTowerStatusDataService(SysParameterService sysParameterService, WindTowerStatusDataRepository windTowerStatusDataRepository, ProtocolGatherDataPointService protocolGatherDataPointService) {
    this.sysParameterService = sysParameterService;
    this.layerConcerned = Arrays.asList(sysParameterService.getSysParameter(LAYER_CONCERNED, LAYER_CONCERNED_DEFAULT).split(","));
    this.windTowerStatusDataRepository = windTowerStatusDataRepository;
    this.protocolGatherDataPointService = protocolGatherDataPointService;
  }

  public WindTowerStatusData save(WindTowerStatusData windTowerStatusData) {
    checkForDeadValue(windTowerStatusData);
    this.abnormalSignMap.put(windTowerStatusData.getEquipmentNo(), windTowerStatusData.getAbnormalCode());
    return windTowerStatusDataRepository.save(windTowerStatusData);
  }


  /**
   * 获取当前所有测风塔的值是否是异常值
   *
   * @return {@link Boolean
   */
  public Boolean getIsAbnormalData() {
    Collection<AbnormalCode> set = this.abnormalSignMap.values();
    for (AbnormalCode code : set) {
      if (AbnormalCode.NORMAL != code) {
        return true;
      }
    }
    return false;
  }

  /**
   * 获取当前所有测风塔的值是否是异常值
   *
   * @return {@link Boolean
   */
  public String getIsAbnormalInfo() {
    StringBuilder str = new StringBuilder();
    for (Map.Entry<Integer, AbnormalCode> e : this.abnormalSignMap.entrySet()) {
      str.append("测风塔-" + e.getKey() + "," + e.getValue().getErrInfo());
    }
    return str.toString();
  }

  /**
   * 该测风塔是否是异常的
   *
   * @param windTowerId 风塔id
   * @return {@link Boolean}
   */
  public AbnormalCode getIsAbnormalData(Integer windTowerId) {
    return this.abnormalSignMap.getOrDefault(windTowerId, AbnormalCode.NORMAL);
  }

  /**
   * 检查10个风塔数据是否有死值或者空值存在
   * 只要1个风速存在死值 或者空值 便将异常置入数据状态
   */
  private void checkForDeadValue(WindTowerStatusData windTowerStatusData) {
    if (windTowerStatusData.getEquipmentNo() == null) {
      return;
    }
    if (!deadValueCheckers.containsKey(windTowerStatusData.getEquipmentNo())) {
      this.deadValueCheckers.put(windTowerStatusData.getEquipmentNo(), new DeadValueChecker(windTowerStatusData.getEquipmentNo()));
    }
    AbnormalCode e = deadValueCheckers.get(windTowerStatusData.getEquipmentNo()).addWindTowerData(windTowerStatusData);
    windTowerStatusData.setAbnormalCode(e);
  }


  public List<WindTowerStatusData> findByEquipmentNoAndTimeBetween(Integer equipmentNo, Date startTime, Date endTime) {
    return windTowerStatusDataRepository.findByEquipmentNoAndTimeBetween(equipmentNo, startTime, endTime);
  }


  /**
   * 死值检查
   *
   * @author xiuwei
   * @date 2021/10/18
   */

  private class DeadValueChecker {

    /**
     * 正则表达式
     */
    private final Pattern pattern = Pattern.compile("[0-9]{1,2}[0]$");

    private final Set layerSet = new HashSet();

    public DeadValueChecker(Integer equipmentNo) {
      this.equipmentNo = equipmentNo;
      List<ProtocolGatherDataPoint> pList = protocolGatherDataPointService.getByEquipmentId(equipmentNo, EquipmentTypeEnum.WINDTOWER);
      for (ProtocolGatherDataPoint p : pList) {
        Matcher m = pattern.matcher(p.getEquipmentAttribute().getFieldName());
        if (m.find()) {
          layerSet.add(m.group());
        }
      }
      layerSet.add("HUB");
      layerSet.retainAll(getLayerConcerned());
    }

    Integer equipmentNo;


    /**
     * 最近10个风塔状态数据
     */
    ArrayList<WindTowerStatusData> windTowerStatusDataLastTen = new ArrayList<>();

    /**
     * 10米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInst10 = new BigDecimal(-99);

    /**
     * 10 米风速死值个数
     */
    private Integer ws10Times = 0;


    /**
     * 30米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInst30 = new BigDecimal(-99);

    /**
     * 30 米风速死值个数
     */
    private Integer ws30Times = 0;


    /**
     * 50米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInst50 = new BigDecimal(-99);

    /**
     * 50 米风速死值个数
     */
    private Integer ws50Times = 0;


    /**
     * 60米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInst60 = new BigDecimal(-99);

    /**
     * 60 米风速死值个数
     */
    private Integer ws60Times = 0;


    /**
     * 70米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInst70 = new BigDecimal(-99);

    /**
     * 70 米风速死值个数
     */
    private Integer ws70Times = 0;


    /**
     * 80米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInst80 = new BigDecimal(-99);

    /**
     * 80 米风速死值个数
     */
    private Integer ws80Times = 0;


    /**
     * 90米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInst90 = new BigDecimal(-99);

    /**
     * 90 米风速死值个数
     */
    private Integer ws90Times = 0;

    /**
     * 100米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInst100 = new BigDecimal(-99);

    /**
     * 100 米风速死值个数
     */
    private Integer ws100Times = 0;


    /**
     * Hub米风速瞬时值（m/s） 上一个值
     */
    private BigDecimal wsInstHub = new BigDecimal(-99);

    /**
     * Hub 米风速死值个数
     */
    private Integer wsHubTimes = 0;


    /**
     * 添加风塔数据  并返回是否是死值
     *
     * @param windTowerStatusData 风塔状态数据
     * @return boolean
     */
    public AbnormalCode addWindTowerData(WindTowerStatusData windTowerStatusData) {
      Set<AbnormalCode> abnormalCodes = new HashSet<>();
      if (this.windTowerStatusDataLastTen.size() >= 10) {
        this.windTowerStatusDataLastTen.remove(0);
      }
      this.windTowerStatusDataLastTen.add(windTowerStatusData);
      if (layerSet.contains("10")) {
        if (isNotBlank(windTowerStatusData.getWsInst10())) {
          if (wsInst10.compareTo(windTowerStatusData.getWsInst10()) == 0) {
            ws10Times++;
            if (ws10Times >= 10) {
              log.info("测风塔" + equipmentNo + "--10米风速死值达到{}次", ws10Times);
              abnormalCodes.add(AbnormalCode.DEAD10);
            }
          } else {
            ws10Times = 0;
            this.wsInst10 = windTowerStatusData.getWsInst10();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--10米风速为空值");
          ws10Times = 0;
          abnormalCodes.add(AbnormalCode.NULL10);
        }
      }
      if (layerSet.contains("30")) {
        if (isNotBlank(windTowerStatusData.getWsInst30())) {
          if (wsInst30.compareTo(windTowerStatusData.getWsInst30()) == 0) {
            ws30Times++;
            if (ws30Times >= 10) {
              log.info("测风塔" + equipmentNo + "--30米风速死值达到{}次", ws30Times);
              abnormalCodes.add(AbnormalCode.DEAD30);
            }
          } else {
            ws30Times = 0;
            this.wsInst30 = windTowerStatusData.getWsInst30();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--30米风速为空值");
          ws30Times = 0;
          abnormalCodes.add(AbnormalCode.NULL30);
        }
      }
      if (layerSet.contains("50")) {
        if (isNotBlank(windTowerStatusData.getWsInst50())) {
          if (wsInst50.compareTo(windTowerStatusData.getWsInst50()) == 0) {
            ws50Times++;
            if (ws50Times >= 10) {
              log.info("测风塔" + equipmentNo + "--50米风速死值达到{}次", ws50Times);
              abnormalCodes.add(AbnormalCode.DEAD50);
            }
          } else {
            ws50Times = 0;
            this.wsInst50 = windTowerStatusData.getWsInst50();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--50米风速为空值");
          ws50Times = 0;
          abnormalCodes.add(AbnormalCode.NULL50);
        }
      }
      if (layerSet.contains("60")) {
        if (isNotBlank(windTowerStatusData.getWsInst60())) {
          if (wsInst60.compareTo(windTowerStatusData.getWsInst60()) == 0) {
            ws60Times++;
            if (ws60Times >= 10) {
              log.info("测风塔" + equipmentNo + "--60米风速死值达到{}次", ws60Times);
              abnormalCodes.add(AbnormalCode.DEAD60);
            }
          } else {
            ws60Times = 0;
            this.wsInst60 = windTowerStatusData.getWsInst60();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--60米风速为空值");
          ws60Times = 0;
          abnormalCodes.add(AbnormalCode.NULL60);
        }
      }
      if (layerSet.contains("70")) {
        if (isNotBlank(windTowerStatusData.getWsInst70())) {
          if (wsInst70.compareTo(windTowerStatusData.getWsInst70()) == 0) {
            ws70Times++;
            if (ws70Times >= 10) {
              log.info("测风塔" + equipmentNo + "--70米风速死值达到{}次", ws70Times);
              abnormalCodes.add(AbnormalCode.DEAD70);
            }
          } else {
            ws70Times = 0;
            this.wsInst70 = windTowerStatusData.getWsInst70();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--70米风速为空值");
          ws70Times = 0;
          abnormalCodes.add(AbnormalCode.NULL70);
        }
      }
      if (layerSet.contains("80")) {
        if (isNotBlank(windTowerStatusData.getWsInst80())) {
          if (wsInst80.compareTo(windTowerStatusData.getWsInst80()) == 0) {
            ws80Times++;
            if (ws80Times >= 10) {
              log.info("测风塔" + equipmentNo + "--80米风速死值达到{}次", ws80Times);
              abnormalCodes.add(AbnormalCode.DEAD80);
            }
          } else {
            ws80Times = 0;
            this.wsInst80 = windTowerStatusData.getWsInst80();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--80米风速为空值");
          ws80Times = 0;
          abnormalCodes.add(AbnormalCode.NULL80);
        }
      }
      if (layerSet.contains("90")) {
        if (isNotBlank(windTowerStatusData.getWsInst90())) {
          if (wsInst90.compareTo(windTowerStatusData.getWsInst90()) == 0) {
            ws90Times++;
            if (ws90Times >= 10) {
              log.info("测风塔" + equipmentNo + "--90米风速死值达到{}次", ws90Times);
              abnormalCodes.add(AbnormalCode.DEAD90);
            }
          } else {
            ws90Times = 0;
            this.wsInst90 = windTowerStatusData.getWsInst90();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--90米风速为空值");
          ws90Times = 0;
          abnormalCodes.add(AbnormalCode.NULL90);
        }
      }
      if (layerSet.contains("100")) {
        if (isNotBlank(windTowerStatusData.getWsInst100())) {
          if (wsInst100.compareTo(windTowerStatusData.getWsInst100()) == 0) {
            ws100Times++;
            if (ws100Times >= 10) {
              log.info("测风塔" + equipmentNo + "--100米风速死值达到{}次", ws100Times);
              abnormalCodes.add(AbnormalCode.DEAD100);
            }
          } else {
            ws100Times = 0;
            this.wsInst100 = windTowerStatusData.getWsInst100();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--100米风速为空值");
          ws100Times = 0;
          abnormalCodes.add(AbnormalCode.NULL100);
        }
      }
      if (layerSet.contains("HUB")) {
        if (isNotBlank(windTowerStatusData.getWsInstHubHeight())) {
          if (wsInstHub.compareTo(windTowerStatusData.getWsInstHubHeight()) == 0) {
            wsHubTimes++;
            if (wsHubTimes >= 10) {
              log.info("测风塔" + equipmentNo + "--Hub米风速死值达到{}次", wsHubTimes);
              abnormalCodes.add(AbnormalCode.DEADHUB);
            }
          } else {
            wsHubTimes = 0;
            this.wsInstHub = windTowerStatusData.getWsInstHubHeight();
          }
        } else {
          log.info("测风塔" + equipmentNo + "--Hub米风速为空值");
          wsHubTimes = 0;
          abnormalCodes.add(AbnormalCode.NULLHUB);
        }
      }
      if (abnormalCodes.size() >= 1) {
        return abnormalCodes.iterator().next();
      }
      return AbnormalCode.NORMAL;
    }


    /**
     * 判断数据是否是空
     *
     * @param ws ws
     * @return boolean
     */
    public boolean isNotBlank(BigDecimal ws) {
      return ws != null && ws.compareTo(BigDecimal.valueOf(-99)) != 0;
    }


  }

}
