package be.iminds.ilabt.jfed.highlevel.jobs.report;

import be.iminds.ilabt.jfed.call_log_output.HtmlLogOutput;
import be.iminds.ilabt.jfed.call_log_output.SerializableApiCallDetails;
import be.iminds.ilabt.jfed.experiment.tasks.ExperimentTaskStatus;
import be.iminds.ilabt.jfed.highlevel.controller.TaskExecution;
import be.iminds.ilabt.jfed.log.cache.ApiCallDetailsCache;
import org.rendersnake.HtmlCanvas;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * User: twalcari
 * Date: 12/11/2015
 * Time: 11:29
 */
public class StitchingJobReportWriter extends HtmlLogOutput {

    private final StitchingJobReport jobReport;
    private final ApiCallDetailsCache cache;

    public StitchingJobReportWriter(StitchingJobReport jobReport, ApiCallDetailsCache cache) {
        super("Start Stitching Experiment Report");
        this.jobReport = jobReport;
        this.cache = cache;
    }

    @Override
    public void htmlContent(HtmlCanvas html) throws IOException {
        addClassVisibleToggle(html, "logline-DEBUG", "Debug Log Lines");

        int index = 0;
        for (JobStateReport reportState : jobReport.getJobStateReports()) {
            List<SerializableApiCallDetails> callsCopy;
            List<LogEntry> logsCopy;
            synchronized (reportState.getTaskExecutions()) {
                callsCopy = reportState.getTaskExecutions().stream()
                        .filter(Objects::nonNull)
                        .flatMap(taskExecution -> taskExecution.getApiCallHistory().stream())
                        .map(cache::getApiCallDetails).collect(Collectors.toList());
            }
            synchronized (reportState.getLogLines()) {
                logsCopy = new ArrayList<>(reportState.getLogLines());
            }
            writeGroup(html,
                    index++,
                    convertExperimentTaskStatus(reportState.getFinalStatus()),
                    reportState.getStateName() + " calls",
                    "Executed tasks: " + reportState.getTaskExecutions().stream().map(TaskExecution::getName).collect(Collectors.joining(", ")),
                    Duration.between(reportState.getStartTime(),
                            reportState.getEndTime() != null ? reportState.getEndTime() : Instant.now()).toMillis(),
                    Date.from(reportState.getStartTime()),
                    Date.from(reportState.getEndTime()),
                    (String) null/*exception*/,
                    callsCopy,
                    logsCopy);
        }
    }

    private static TestResultState convertExperimentTaskStatus(ExperimentTaskStatus status) {
        switch (status) {
            case SUCCESS:
                return TestResultState.SUCCESS;
            case FAILED:
                return TestResultState.FAILED;
            case WARNING:
                return TestResultState.WARN;
            default:
                return null;

        }
    }
}
