package cz.muni.disa.adamiss.se.stats.runners;

import cz.muni.disa.adamiss.core.common.enums.ParameterName;
import cz.muni.disa.adamiss.core.objects.Operator;
import cz.muni.disa.adamiss.se.common.Algo;
import cz.muni.disa.adamiss.se.operators.GSP;
import cz.muni.disa.adamiss.se.operators.PrefixSpan;
import cz.muni.disa.adamiss.se.operators.Spam;
import cz.muni.disa.adamiss.se.stats.objects.ExperimentReport;
import cz.muni.disa.adamiss.se.structures.DatasetContainer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExperimentRunner {
    public static Logger logger = LogManager.getLogger(ExperimentRunner.class);

    public static ExperimentReport run(String name, DatasetContainer container, int threshold, Algo algo) {

        logger.debug("Running experiment: (" + container.name() + ", " + algo.toString() + ", " + threshold + ")");
        Map<String, Object> params = new HashMap<>();
        params.put(ParameterName.miningThreshold.toString(), threshold);
        Operator operator;
        switch (algo) {
            case GSP -> operator = new GSP();
            case PREFIX_SPAN -> operator = new PrefixSpan();
            case SPAM -> operator = new Spam();
            //case SPADE -> operator = new Spade();
            default -> throw new IllegalStateException("Unexpected value: " + algo);
        }

        long startTime = System.currentTimeMillis();
        operator.apply(container.dataset(), params);
        long time = System.currentTimeMillis() - startTime;


        logger.debug("Experiment ended in : " + time + "ms");
        return new ExperimentReport(name, container.dbReport(), threshold, time, algo);
    }

    public static List<ExperimentReport> runAll(List<DatasetContainer> containers) {
        List<ExperimentReport> result = new ArrayList<>();
        for (DatasetContainer container : containers) {
            for (int threshold : container.name().getSupports()) {
                for (Algo algo : Algo.values()) {
                    result.add(run(container.name() + "_" + algo + "_" + threshold, container, threshold, algo));
                }
            }
        }
        return result;
    }

}
