package cz.senslog.analytics.messaging;

import cz.senslog.analytics.domain.ValidationResult;
import cz.senslog.analytics.domain.ThresholdViolationNotification;
import io.vertx.core.json.JsonObject;

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;

@FunctionalInterface
public interface MessageBroker {
    enum Type {
        SENSLOG_ALERT   (SensLogAlertMessageBroker::new),

        ;
        private final Function<JsonObject, MessageBroker> constructCreator;

        Type(Function<JsonObject, MessageBroker> constructCreator) {
            this.constructCreator = constructCreator;
        }

        public MessageBroker createBroker(JsonObject config) {
            return constructCreator.apply(config);
        }
    }

    void send(ThresholdViolationNotification notification, JsonObject recipients);

    default String createMessage(ThresholdViolationNotification n) {
        ValidationResult[] violatedData = n.violatedData();
        if (violatedData.length == 0) {
            return null;
        }
        StringBuilder b = new StringBuilder();
        b.append(createLineMessage(n.moduleName(), n.sourceName(), violatedData[0], n.timestamp()));
        for (int i = 1; i < violatedData.length; i++) {
            b.append("\n").append(createLineMessage(n.moduleName(), n.sourceName(), violatedData[i], n.timestamp()));
        }
        return b.toString();
    }

    default String createLineMessage(String moduleName, String sourceName, ValidationResult validationResult, OffsetDateTime timestamp) {
        final String delimiter = " ";
        String sourceStr = moduleName + delimiter + sourceName;
        String attrValue = String.format("%s(%.2f)", validationResult.attribute(), validationResult.validatedValue());
        String timestampStr = "at" + delimiter + timestamp.format(DateTimeFormatter.ISO_DATE_TIME);
        List<ValidationResult.Record> records = validationResult.records();
        if (records.isEmpty()) {
            return sourceStr + delimiter + timestampStr;
        }
        Iterator<ValidationResult.Record> recIter = records.iterator();
        ValidationResult.Record rec1 = recIter.next();
        StringBuilder rulesStr = new StringBuilder(String.format("%s %s %.2f", attrValue, rec1.mode(), rec1.thresholdValue()));
        while (recIter.hasNext()) {
            ValidationResult.Record rec = recIter.next();
            rulesStr.append(String.format("&& %s %s %.2f", attrValue, rec.mode(), rec.thresholdValue()));
        }
        return sourceStr + delimiter + rulesStr + delimiter + timestampStr;
    }
}
