package com.xydl.cac.task;

import com.xydl.cac.entity.ModevTypePoint;
import com.xydl.cac.entity.NSensor;
import com.xydl.cac.entity.WarnRule;
import com.xydl.cac.entity.Warning;
import com.xydl.cac.entity.constants.Constants;
import com.xydl.cac.model.StaticVariable;
import com.xydl.cac.model.TriggerModel;
import com.xydl.cac.repository.WarnRuleRepository;
import com.xydl.cac.repository.WarningRepository;
import com.xydl.cac.serialport.SerialPortServer;
import com.xydl.cac.service.DataService;
import com.xydl.cac.socket.WebSocketServer;
import com.xydl.cac.util.DateUtil;
import com.xydl.cac.util.DingTalkPushUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.*;

@Service
@Slf4j
public class RuleCheckTask {
    @Resource
    WarnRuleRepository ruleRepository;
    @Resource
    DataService dataService;
    @Resource
    WarningRepository warningRepository;
    @Resource
    DingTalkPushUtil dingTalkPushUtil;
    @Resource
    WebSocketServer webSocketServer;
    @Resource
    SerialPortServer serialPortServer;

    int shutdown = 0;

    @PreDestroy
    private void preDestroy() {
        shutdown = 1;
    }

    @Scheduled(initialDelay = 60 * 1000, fixedDelay = 3 * 60 * 1000)
    private void checkAll() {
        try {
            Iterator<Integer> it = StaticVariable.rule_Cache.keySet().iterator();
            while (it.hasNext()) {
                Integer key = it.next();
                WarnRule rule = StaticVariable.rule_Cache.get(key);
                if (rule.canDo()) {
                    this.ruleCheck(rule);
                }
            }
        } catch (Exception e) {
            log.error("RuleCheckTask.checkAll error.", e);
        }
    }

    private void ruleCheck(WarnRule rule) {
        if (shutdown == 1) {
            return;
        }
        try {
            NSensor sensor = rule.getNSensor();
            ModevTypePoint typePoint = rule.getTypePoint();
            List<ModevTypePoint> points = new ArrayList<>();
            points.add(typePoint);
            List<Map<String, Object>> list = dataService.getLatestData(sensor.getTableName(), sensor.getDevId(), points, rule.getLastDTime());
            List<TriggerModel> warnList = rule.checkData(list);
            if (warnList != null) {
                ruleRepository.save(rule);
                for (TriggerModel model : warnList) {
                    this.sendWarning(rule, model);
                }
                if (warnList.size() > 0 &&
                        rule.getNotifyCom() != null && rule.getNotifyCom().intValue() == Constants.TRUE) {
                    // 通知串口
                    serialPortServer.sendData();
                }
            }
        } catch (Exception e) {
            log.error("RuleCheckTask.ruleCheck error. ruleId=" + rule.getId(), e);
        }
    }

    private void sendWarning(WarnRule rule, TriggerModel model) throws Exception {
        if (shutdown == 1) {
            return;
        }
        NSensor sensor = rule.getNSensor();
        ModevTypePoint typePoint = rule.getTypePoint();
        Warning warning = Warning.builder()
                .sensorId(sensor.getId())
                .sensorName(sensor.getName())
                .zsbName(sensor.getZsbName())
                .ruleId(rule.getId())
                .field(typePoint.getField())
                .dTime(model.getDTime())
                .threshold(rule.getThreshold())
                .warnValue(model.getValue())
                .warnLevel(rule.getLevel())
                .state("1")
                .warnDesc(sensor.getName() + " " + typePoint.getFieldDesc() + " 告警")
                .triggerDesc(rule.getOperatorDesc() + " 阈值(" + rule.getThreshold() + ")")
                .warnTime(new Date())
                .processTime(new Date())
                .build();
        warningRepository.save(warning);
        String str = warning.getZsbName() + "--" + warning.getWarnDesc() + " "
                + warning.getTriggerDesc() + ", 当前值:" + model.getValue();
        if (model.getDTime() != null) {
            str = str + ", 采集时间:" + DateUtil.format(model.getDTime());
        }
        if (model.getLastDTime() != null) {
            str = str + ", 最后采集时间:" + DateUtil.format(model.getLastDTime());
        }
        log.warn("触发规则告警: " + str);
        webSocketServer.sendMessage(str, warning.getId());
//        dingTalkPushUtil.pushText(str);
    }

}
