package com.eactive.eai.custom.alarm;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;

import org.springframework.stereotype.Service;

import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.Jsons;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.custom.alarm.key.AlarmKey;
import com.eactive.eai.custom.alarm.key.DynamicAlarmKey;
import com.eactive.eai.custom.alarm.policy.AlarmPolicy;
import com.eactive.eai.custom.alarm.policy.CounterPolicy;
import com.eactive.eai.custom.alarm.policy.SendPolicy;
import com.eactive.eai.custom.alarm.policy.TimerPolicy;
import com.google.gson.JsonObject;

@Service
public class AlarmService {

    protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

    final static String ALARM_GROUP = "Alarm";
    final static String ALARM_KEY = "{ALARM}";
    final static String ALARM_RECIVER = "{RECIVER}";
    final static String ALARM_EABLE = "enable.alarm";

    public Map<AlarmKey, AlarmPolicy> getAlarmPolicy() {

	Map<AlarmKey, AlarmPolicy> policyMap = new HashMap<AlarmKey, AlarmPolicy>();

	try {

	    Properties props = PropManager.getInstance().getProperties(ALARM_GROUP);

	    props.forEach((key, value) -> {

		String keyName = (String) key;
		String configStr = (String) value;

		if (keyName.contains(ALARM_KEY)) {

		    AlarmPolicy newPolicy = buildAlarmPolicy(keyName, configStr);
		    policyMap.put(newPolicy.getAlarmKey(), newPolicy);

		}
	    });

	} catch (Exception e) {
	    logger.warn("getAlarmPolicy fail.", e);
	    return Collections.EMPTY_MAP;
	}

	return policyMap;
    }

    public boolean isAlarmEnabled() {
	return Optional.ofNullable(PropManager.getInstance().getProperty(ALARM_GROUP, ALARM_EABLE))
		.map(Boolean::valueOf).orElse(false);
    }

    private AlarmPolicy buildAlarmPolicy(String key, String configJsonStr) {

	JsonObject alarmConfig = Jsons.GSON.fromJson(configJsonStr, JsonObject.class);

	String policyType = alarmConfig.get("type").getAsString();
	int thresholdCount = Optional.ofNullable(alarmConfig.get("thresholdCount")).map(i -> i.getAsInt()).orElse(5);
	int timeWindowSec = Optional.ofNullable(alarmConfig.get("timeWindowSec")).map(i -> i.getAsInt()).orElse(60);

	AlarmPolicy alarmPolicy;

	if ("count".equals(policyType)) {
	    alarmPolicy = CounterPolicy.builder().alarmKey(new DynamicAlarmKey(key)).thresholdCount(thresholdCount)
		    .build();
	} else {
	    alarmPolicy = TimerPolicy.builder().alarmKey(new DynamicAlarmKey(key)).timeWindowMs(timeWindowSec * 1000)
		    .build();
	}

	return alarmPolicy;

    }

    public Map<AlarmKey, SendPolicy> getSendPolicy() {

	Map<AlarmKey, SendPolicy> policyMap = new HashMap<AlarmKey, SendPolicy>();

	try {

	    Properties props = PropManager.getInstance().getProperties(ALARM_GROUP);

	    props.forEach((key, value) -> {
		String keyName = (String) key;
		String configStr = (String) value;

		if (!keyName.contains(ALARM_RECIVER))
		    return;

		SendPolicy newPolicy = buildSendPolicy(keyName, configStr);

		policyMap.put(newPolicy.getAlarmKey(), newPolicy);

	    });

	} catch (Exception e) {
	    logger.warn("getSendPolicy fail.", e);
	    return Collections.EMPTY_MAP;
	}

	return policyMap;
    }

    private SendPolicy buildSendPolicy(String key, String configStr) {

	List<String> reciverList = Optional.ofNullable(configStr).map(t -> Arrays.asList(t.split(",")))
		.orElse(Collections.EMPTY_LIST);

	key = key.replace(ALARM_RECIVER, "").trim() + "{ALARM}";

	SendPolicy sendPolicy = new SendPolicy(key, reciverList);

	return sendPolicy;

    }
}
