package com.jiayue.ipfcst.dataexchange.domain;

import com.jiayue.ipfcst.common.core.exception.BusinessException;
import com.jiayue.ipfcst.common.core.util.SpringContextHolder;
import com.jiayue.ipfcst.common.data.constant.enums.DataSourceEnum;
import com.jiayue.ipfcst.common.data.entity.EquipmentAttribute;
import com.jiayue.ipfcst.common.data.entity.ProtocolDataType;
import com.jiayue.ipfcst.common.data.entity.ProtocolGatherDataPoint;
import com.jiayue.ipfcst.dataexchange.service.ProtocolGatherDataPointService;
import com.jiayue.ipfcst.dataexchange.service.TemplatePointService;
import lombok.Data;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import javax.persistence.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 模版下的点位描述
 *
 * @author 修唯xiuwei
 * @version 3.0
 */
@Entity
@Data
public class TemplatePoint {


  private static final Pattern expr = Pattern.compile("(?<=P_).*?(?=_P)");
  /**
   * 允许的最大变化值
   */
  @Column(precision = 7, scale = 2)
  Double maxChangeValue;
  /**
   * 允许的最大值
   */
  @Column(precision = 7, scale = 2)
  Double maxValue;
  /**
   * 允许的最小值
   */
  @Column(precision = 7, scale = 2)
  Double minValue;
  /**
   * 该数据点位是否需要数据合理性考核
   */
  @Column(columnDefinition = "bit(1)  default false")
  Boolean needAudit;
  /**
   * 允许数值不发生变化的最长时长   单位为 min 分钟
   * 当值为空时 说明不限制时长
   */
  Long maxDuration;
  /**
   * 顺序号
   */
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO, generator = "myid")
  @GenericGenerator(name = "myid", strategy = "com.jiayue.ipfcst.common.data.entity.id.CustomIDGenerator")
  private Integer id;
  /*@ManyToOne(cascade= CascadeType.ALL)
  @JoinColumn(referencedColumnName = "id" )
  @JsonIgnore*/
  private Integer equipmentDataTemplateId;
  /**
   * 该点位在模版中的顺序
   */
  @Column(length = 4)
  private Integer sequence;
  /**
   * 该点位是否是采集得到还是通过规则生成
   */
  @Column(length = 1)
  private DataSourceEnum dataSource;
  /**
   * 通道号
   */
  @Column(length = 32)
  private String tunnelId;
  /**
   * 设备属性 对应点位根据寻位标识生成的规则
   */
  private String pointRegulation;
  /**
   * 通道协议中对应的数据类型
   */
  @Column(length = 9)
  @Enumerated(EnumType.STRING)
  private ProtocolDataType protocolPointType;
  /**
   * 协议点描述的设备属性
   */
  @OneToOne
  @JoinColumn(name = "equipmentAttributeId", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
  private EquipmentAttribute equipmentAttribute;
  /**
   * 倍率
   */
  @Column(precision = 10, scale = 4)
  private Double magnification = 1D;
  /**
   * 用于生成需要内部生成的属性的规则
   */
  @Lob
  private String generationRegulation;
  /**
   * 是否使用
   */
  private Boolean isUsing;
  /**
   * 场站标识
   */
  @Column
  private String stationCode;

  /**
   * 由模版点位转化成采集点位
   *
   * @return 采集点位 实体
   */
  public ProtocolGatherDataPoint turnGatherDataPoint() {
    ProtocolGatherDataPoint protocolGatherDataPoint = new ProtocolGatherDataPoint();
    protocolGatherDataPoint.setDataSource(this.dataSource);
    protocolGatherDataPoint.setEquipmentAttribute(this.equipmentAttribute);
    protocolGatherDataPoint.setTunnelId(this.tunnelId);
    protocolGatherDataPoint.setProtocolPointType(this.protocolPointType);
    protocolGatherDataPoint.setMagnification(this.magnification);
    protocolGatherDataPoint.setNeedAudit(this.needAudit);
    protocolGatherDataPoint.setMaxChangeValue(this.maxChangeValue);
    protocolGatherDataPoint.setMaxValue(this.maxValue);
    protocolGatherDataPoint.setMinValue(this.minValue);
    protocolGatherDataPoint.setMaxDuration(this.maxDuration);
    return protocolGatherDataPoint;
  }

  /**
   * 重载上一个方法  根据寻址位生成采集点表的通道顺序位
   *
   * @param findAddressN 寻址位 N 值
   * @return 采集点位 实体
   */
  public ProtocolGatherDataPoint turnGatherDataPoint(Integer findAddressN) {
    String parserString = "";
    ProtocolGatherDataPoint protocolGatherDataPoint = turnGatherDataPoint();
    //通道采集点位， 根据点位生成规则生成采集通道的点位
    parserString = this.getPointRegulation().replace("N", findAddressN + "");
    Integer add = new SpelExpressionParser().parseExpression(parserString).getValue(Integer.class);
    protocolGatherDataPoint.setProtocolPointNo(add);
    return protocolGatherDataPoint;
  }


  /**
   * 重载上一个方法  根据寻址位生成采集点表的通道顺序位
   *
   * @param equipmentId 设备id
   * @return 采集点位 实体
   */
  public ProtocolGatherDataPoint turnGenerateDataPoint(Integer equipmentId) throws BusinessException {
    ProtocolGatherDataPoint protocolGatherDataPoint = turnGatherDataPoint();
    protocolGatherDataPoint.setEquipmentId(equipmentId);
    //生成数据的点位  将模版的公式转化为全局可用的点位
    ProtocolGatherDataPointService protocolGatherDataPointService = SpringContextHolder.getBean(ProtocolGatherDataPointService.class);
    TemplatePointService templatePointService = SpringContextHolder.getBean(TemplatePointService.class);
    ProtocolGatherDataPoint protocolGatherDataPoint1;
    TemplatePoint templatePoint;
    Matcher matcher = expr.matcher(this.generationRegulation);
    String generationRegulation = this.generationRegulation;
    while (matcher.find()) {
      //根据相应的模版id 和模版点顺序找到对应的模版点位
      templatePoint = new TemplatePoint();
      templatePoint.setMagnification(null);
      templatePoint.setEquipmentDataTemplateId(this.equipmentDataTemplateId);
      String s = matcher.group();
      templatePoint.setSequence(Integer.parseInt(s));
      List<TemplatePoint> templatePointList = templatePointService.get(templatePoint);
      if (templatePointList.size() == 1) {
        //根据设备属性和设备id 查找有没相应的点位
        EquipmentAttribute attr = templatePointList.get(0).getEquipmentAttribute();
        protocolGatherDataPoint1 = new ProtocolGatherDataPoint();
        protocolGatherDataPoint1.setEquipmentId(equipmentId);
        protocolGatherDataPoint1.setEquipmentAttribute(attr);
        List<ProtocolGatherDataPoint> protocolGatherDataPointList = protocolGatherDataPointService.get(protocolGatherDataPoint1);
        if (protocolGatherDataPointList.size() == 1) {
          Integer id = protocolGatherDataPointList.get(0).getId();
          generationRegulation = generationRegulation.replace("P_" + s + "_P", "P_" + id + "_P");
        } else if (protocolGatherDataPointList.size() == 0) {
          throw new BusinessException("公式生成引用点位的还没生成，请调整模版点位顺序");
        }
      } else if (templatePointList.size() == 0) {
        throw new BusinessException("该模版中没有对应该顺序的模版点位");
      }
    }
    protocolGatherDataPoint.setGenerationRegulation(generationRegulation);
    return protocolGatherDataPoint;
  }


}
