package cz.senslog.analytics.utils;

import cz.senslog.analytics.domain.*;
import cz.senslog.analytics.utils.validator.DataSource;
import cz.senslog.analytics.utils.validator.NotifyTrigger;
import cz.senslog.analytics.utils.validator.Threshold;

import java.util.*;

import static java.util.Collections.emptyList;

public final class DBDomainToValidator {

    public static NotifyTrigger.Mode toNotifyTrigger(final NotifyTriggerMode dbNotifyTriggerMode) {
        switch (dbNotifyTriggerMode) {
            case DISABLED -> {
                return NotifyTrigger.Mode.DISABLED;
            }
            case ON_CHANGE -> {
                return NotifyTrigger.Mode.ON_CHANGE;
            }
            case INSTANT -> {
                return NotifyTrigger.Mode.INSTANT;
            }
            default -> {
                return null;
            }
        }
    }

    public static Threshold toThreshold(final cz.senslog.analytics.domain.Threshold threshold) {
        List<Threshold.Dimension> dimensions = new ArrayList<>(threshold.thresholdDimensions().size());
        for (ThresholdDimension dm : threshold.thresholdDimensions()) {
            List<Threshold.Dimension.Rule> rules = new ArrayList<>(dm.rules().size());
            for (ThresholdDimensionRule r : dm.rules()) {
                rules.add(new Threshold.Dimension.Rule(r.comparisonOperator(), r.value()));
            }
            dimensions.add(new Threshold.Dimension(dm.attributeType(), toNotifyTrigger(dm.notifyTriggerMode()), rules));
        }
        return new Threshold(
                threshold.id(), threshold.datasourceId(), threshold.enableProcess(), threshold.enableAlert(), threshold.customAlertMessage(), dimensions);
    }

    public static List<DataSource> sensorsToDataSources(final String moduleName, final Collection<Sensor> sensors, final Collection<cz.senslog.analytics.domain.Threshold> thresholds) {
        final Map<Long, List<Threshold>> thresholdsMap = new HashMap<>();
        for (cz.senslog.analytics.domain.Threshold th : thresholds) {
            thresholdsMap.computeIfAbsent(th.datasourceId(), dsID -> new ArrayList<>()).add(toThreshold(th));
        }
        final List<DataSource> dataSources = new ArrayList<>(thresholdsMap.size());
        for (Sensor s : sensors) {
            final long datasourceId = s.id();
            dataSources.add(new DataSource(datasourceId, s.name(), moduleName, thresholdsMap.getOrDefault(datasourceId, emptyList())));
        }
        return dataSources;
    }

    public static List<DataSource> groupsToDataSources(final String moduleName, final Collection<AnalyticGroup> analyticGroups, final Collection<cz.senslog.analytics.domain.Threshold> thresholds) {
        final Map<Long, List<Threshold>> thresholdsMap = new HashMap<>(analyticGroups.size());
        for (cz.senslog.analytics.domain.Threshold th : thresholds) {
            thresholdsMap.computeIfAbsent(th.datasourceId(), dsID -> new ArrayList<>()).add(toThreshold(th));
        }
        final List<DataSource> dataSources = new ArrayList<>(thresholdsMap.size());
        for (AnalyticGroup ag : analyticGroups) {
            final long datasourceId = ag.id();
            dataSources.add(new DataSource(datasourceId, ag.name(), moduleName, thresholdsMap.getOrDefault(datasourceId, emptyList())));
        }
        return dataSources;
    }
}
