package com.xydl.cac.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.xydl.cac.comparator.Comparator;
import com.xydl.cac.comparator.FloatCompare;
import com.xydl.cac.comparator.IntCompare;
import com.xydl.cac.comparator.MissCompare;
import com.xydl.cac.entity.constants.Constants;
import com.xydl.cac.model.TriggerModel;
import com.xydl.cac.util.DateUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "warn_rule")
@ApiModel("告警规则表")
@Slf4j
public class WarnRule {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @NotNull(message = "监测装置ID不能为空")
    @ApiModelProperty("监测装置ID")
    @Column(name = "sensor_id")
    private Integer sensorId;

    @NotNull(message = "监测装置属性点Id不能为空")
    @ApiModelProperty("监测装置属性点Id")
    @Column(name = "modevtype_point_id")
    private Integer modevtypePointId;

    @NotBlank(message = "阈值不能为空")
    @ApiModelProperty("阈值")
    @Column(name = "threshold")
    private String threshold;

    @NotBlank(message = "比较器不能为空")
    @ApiModelProperty("比较器")
    @Column(name = "comparator")
    private String comparator;

    @NotBlank(message = "比较符不能为空")
    @ApiModelProperty("比较符")
    @Column(name = "operator")
    private String operator;

    @NotNull(message = "告警级别不能为空")
    @ApiModelProperty("告警级别 0:低 1:中 2:高")
    @Column(name = "level")
    private Integer level;

    @NotNull(message = "状态不能为空")
    @ApiModelProperty("状态 0:停用 1:启用")
    @Column(name = "active")
    private Integer active;

    @ApiModelProperty("状态 0:不通知 1:通知")
    @Column(name = "notify_com")
    private Integer notifyCom;

    @ApiModelProperty("最后数据采集时间")
    @Column(name = "last_d_time")
    private Date lastDTime;

    @Transient
    private String comparatorDesc;
    @Transient
    private String operatorDesc;

    @Transient
    private NSensor nSensor;
    @Transient
    private ModevTypePoint typePoint;
    @Transient
    @JsonIgnore
    private Comparator actualComp;

    public void initComparator(String comparator, String operator) {
        if (actualComp != null && this.comparator.equals(comparator)) {
            this.operator = operator;
            actualComp.setOperator(operator);
        } else {
            this.comparator = comparator;
            this.operator = operator;
            if (Constants.Float.equalsIgnoreCase(comparator)) {
                actualComp = new FloatCompare();
                actualComp.setOperator(operator);
            } else if (Constants.Int.equalsIgnoreCase(comparator)) {
                actualComp = new IntCompare();
                actualComp.setOperator(operator);
            } else if (Constants.Miss.equalsIgnoreCase(comparator)) {
                actualComp = new MissCompare();
                actualComp.setOperator(operator);
            } else {
                actualComp = null;
                log.error("该规则(" + id + ")比较器(" + comparator + ")异常");
            }
        }
        if (actualComp != null) {
            this.operatorDesc = actualComp.supportedOperator().get(this.operator);
        }
    }

    public boolean canDo() {
        if (active != null && active.intValue() == Constants.TRUE &&
                actualComp != null && nSensor != null && typePoint != null) {
            return true;
        }
        return false;
    }

    // 单个数据是否触发
    public boolean triggerRule(Object value) {
        return actualComp.compare(value, threshold, lastDTime);
    }

    // 多数据触发返回告警数据
    public List<TriggerModel> checkData(List<Map<String, Object>> list) throws Exception {
        List<TriggerModel> result = null;
        if (CollectionUtils.isEmpty(list)) {
            if (Constants.Miss.equalsIgnoreCase(comparator)) {
                boolean r = this.triggerRule(null);
                if (r) {
                    result = new ArrayList<>();
                    TriggerModel model = new TriggerModel();
                    model.setLastDTime(lastDTime);
                    model.setValue(String.valueOf(actualComp.getHours()));
                    result.add(model);
                }
            }
        } else {
            result = new ArrayList<>();
            for (Map<String, Object> map : list) {
                String str = (String) map.get("acquisitionTime");
                lastDTime = DateUtil.parse(str);
                Object value = map.get(typePoint.getField());
                boolean r = this.triggerRule(value);
                if (r) {
                    TriggerModel model = new TriggerModel();
                    model.setDTime(lastDTime);
                    model.setValue(String.valueOf(value));
                    result.add(model);
                }
            }
        }
        return result;
    }
}