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

import be.iminds.ilabt.jfed.experiment.Experiment;
import be.iminds.ilabt.jfed.highlevel.controller.Task;
import be.iminds.ilabt.jfed.highlevel.controller.TaskExecution;
import be.iminds.ilabt.jfed.highlevel.controller.TaskExecutionFinishedCallback;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;

import java.util.concurrent.Callable;

/**
 * A job will go through one or more states to complete. All logic and external calls are done in a State.
 * The logic of a job itself should only comprise the decisions of which state is activated next.
 * <p>
 * A job is largel
 * <p>
 * User: twalcari
 * Date: 7/13/2015
 * Time: 16:28
 */
public interface Job<V> extends Callable<V> {
    /**
     * @return The experiment on which the job is called
     */
    Experiment getExperiment();

    /**
     * @return The name of the job, which can be displayed to the end-user
     */
    String getName();

    /**
     * Convenience method for executing tasks which are part of the job.
     *
     * @param task      Task to be executed
     * @param callback Callback to be called when the task is finished
     * @param <T>       Type of task to be executed
     * @return TaskExecution object for the execution of the task
     */
    <T extends Task> TaskExecution<T> submitTask(T task, TaskExecutionFinishedCallback<T> callback);

    <T extends Task> TaskExecution<T> submitTask(T task);

    /**
     * Convenience method for executing tasks which are part of the job, and waiting until the task has returned.
     *
     * @param task Task to be executed
     * @param <T>  Type of task to be executed
     * @return TaskExecution object for the execution of the task
     * @throws InterruptedException When task is interrupted
     */
    <T extends Task> TaskExecution<T> submitTaskAndWait(T task) throws InterruptedException;

    /**
     * @return Current state of the job. Typically visible to the end-user
     */
    State getState();

    /**
     * @return Current message of the job. Typically displayed to an end-user
     */
    String getMessage();

    ReadOnlyObjectProperty<State> stateProperty();

    ReadOnlyStringProperty messageProperty();


}
