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

import be.iminds.ilabt.jfed.call_log_output.LogOutput;
import be.iminds.ilabt.jfed.highlevel.controller.TaskExecution;
import be.iminds.ilabt.jfed.highlevel.jobs.AbstractJob;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

/**
 * User: twalcari
 * Date: 12/9/2015
 * Time: 16:02
 */
public class JobReport {
    private final AbstractJob<?> job;

    private final ObservableList<JobStateReport> jobStateReports = FXCollections.observableArrayList();
    private JobStateReport currentStateReport = null;

    public JobReport(AbstractJob<?> job) {
        this.job = job;

        assert job.getState() == null : "Cannot attach report to active job";

        job.stateProperty().addListener((observable, oldValue, newValue) -> {
            final JobStateReport jobStateReport = new JobStateReport(newValue);
            newValue.registerStateFinishedListener(state -> jobStateReport.registerEnd(state.getStatus()));

            jobStateReports.add(jobStateReport);
            currentStateReport = jobStateReport;

        });


        job.addTaskExecutionFinishedListener(this::onTaskExecutionFinished);
    }

    private void onTaskExecutionFinished(TaskExecution<?> taskExecution) {
        assert currentStateReport != null;
        currentStateReport.addTaskExecution(taskExecution);
    }

    public ObservableList<JobStateReport> getJobStateReports() {
        return jobStateReports;
    }

    /*
    Logging methods
     */

    public void error(String message, Throwable e) {
        log(message, LogOutput.LogLineType.ERROR, e);
    }

    public void error(String message) {
        error(message, null);
    }

    public void warn(String message, Throwable e) {
        log(message, LogOutput.LogLineType.WARN, e);
    }

    public void warn(String message) {
        warn(message, null);
    }

    public void info(String message, Throwable e) {
        log(message, LogOutput.LogLineType.NOTE, e);
    }

    public void info(String message) {
        info(message, null);
    }

    public void debug(String message, Throwable e) {
        log(message, LogOutput.LogLineType.DEBUG, e);
    }

    public void debug(String message) {
        debug(message, null);
    }

    public void log(String message, LogOutput.LogLineType logLineType) {
        this.log(message, logLineType, null);
    }

    public void log(String message, LogOutput.LogLineType logLineType, Throwable e) {
        assert logLineType != null;
        assert message != null;
        log(new LogOutput.LogEntry(logLineType, message, e));
    }

    public void log(LogOutput.LogEntry logEntry) {
        if (currentStateReport != null)
            currentStateReport.addLogLine(logEntry);
    }

    public String getName(){
        return job.getName();
    }


}
