package com.jay.monitor.data.server.report.alert.rule;

import com.jay.monitor.data.server.models.config.AlertSleepModel;
import com.jay.monitor.data.server.models.dto.alert.RealTimeAlert;
import com.jay.monitor.data.server.report.alert.notify.AlertRealTimeMsg;
import com.jay.monitor.data.server.store.ConfigStoreManager;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Module 告警规则抽象类
 * @Description 抽象告警模版
 * @Author liukaixiong
 * @Date 2021/1/20 15:38
 */
public abstract class AbstractAlertRule implements AlertRealTimeMsg {

    @Autowired
    protected ConfigStoreManager configStoreManager;

    /**
     * 休眠间隔记录，记录每次告警时间
     */
    protected Map<String, AlertSleepModel> sleepMap = new ConcurrentHashMap<>();

    /**
     * 是否跳过告警,避免无线循环告警
     *
     * @param msg
     * @return
     */
    @Override
    public boolean isSkipAlert(RealTimeAlert msg) {
        return isSkip(msg, 1);
    }

    private boolean isSkip(RealTimeAlert realTimeAlert, int addNumber) {
        Long alertIntervalMinutes = configStoreManager.getAlertIntervalMinutes();
        long currentTimeMillis = System.currentTimeMillis();
        String key = getCacheKey(realTimeAlert);
        AlertSleepModel alertSleepModel = sleepMap.get(key);
        if (alertSleepModel == null) {
            alertSleepModel = new AlertSleepModel(currentTimeMillis, new AtomicInteger(1));
            sleepMap.put(key, alertSleepModel);
            return false;
        } else {
            // 先自增
            alertSleepModel.getNumber().addAndGet(addNumber);
            Long alertTime = alertSleepModel.getAlertTime();
            long timeInterval = currentTimeMillis - alertTime;
            // 如果没有超过配置的间隔范围
            if (timeInterval < alertIntervalMinutes) {
                return true;
            }

            // 超过间隔范围的情况下，重新计算周期
            // 如果算出来的间隔时间和配置的间隔时间范围过大,也就是超过配置的间隔时间计算周期了,则进行重新计算
            if (timeInterval - alertIntervalMinutes > alertIntervalMinutes) {
                alertSleepModel = new AlertSleepModel(currentTimeMillis, new AtomicInteger(1));
                sleepMap.put(key, alertSleepModel);
            } else {
                alertSleepModel.getNumber().addAndGet(1);
                alertSleepModel.setAlertTime(currentTimeMillis);
                sleepMap.put(key, alertSleepModel);
            }

            return false;
        }
    }

    protected String getCacheKey(RealTimeAlert realTimeAlert) {
        return realTimeAlert.getApplicationName() + "_" + realTimeAlert.getTriggerType();
    }

}
