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

import be.iminds.ilabt.jfed.experiment.Experiment;
import be.iminds.ilabt.jfed.experiment.ExperimentPart;
import be.iminds.ilabt.jfed.experiment.SfaExperimentPart;
import be.iminds.ilabt.jfed.experiment.tasks.ExperimentTaskStatus;
import be.iminds.ilabt.jfed.highlevel.controller.JFedHighLevelException;
import be.iminds.ilabt.jfed.highlevel.controller.TaskThread;
import be.iminds.ilabt.jfed.highlevel.jobs.states.JobStateFactory;
import be.iminds.ilabt.jfed.highlevel.tasks.CreateImageTask;
import be.iminds.ilabt.jfed.highlevel.tasks.HighLevelTaskFactory;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXRspecNode;

import javax.annotation.Nonnull;

/**
 * User: twalcari
 * Date: 12/1/2015
 * Time: 14:45
 */
public class CreateDiskImageJob extends AbstractJob<String> {

    private final FXRspecNode nodeToImage;
    private final String imageName;
    private final boolean global;
    private final boolean updatePrepare;

    private final JobStateFactory jobStateFactory;

    public CreateDiskImageJob(Experiment experiment, FXRspecNode nodeToImage, String imageName,
                              boolean global, boolean updatePrepare,
                              HighLevelTaskFactory hltf, TaskThread tt, JobStateFactory jobStateFactory) {
        super("Create disk image from node " + nodeToImage.getClientId(), experiment, hltf, tt);
        this.nodeToImage = nodeToImage;
        this.imageName = imageName;
        this.global = global;
        this.updatePrepare = updatePrepare;
        this.jobStateFactory = jobStateFactory;
    }

    @Override
    public String execute() throws Exception {

        CreateImageState cis = new CreateImageState();

        setAndRunState(cis);

        if (cis.getStatus() == ExperimentTaskStatus.SUCCESS) {
            final ExperimentPart experimentPart = experiment.getPart(nodeToImage.getSliverId());

            if (experimentPart == null)
                throw new JFedHighLevelException("Could not find ExperimentPart associated with " + nodeToImage.getSliverId());

            if(!(experimentPart instanceof SfaExperimentPart))
                throw new JFedHighLevelException("Expected an SfaExperimentPart, but got an " + experimentPart.getClass().getSimpleName());

            setAndRunState(jobStateFactory.createGetStatusUntilReadyOrFailTaskState(this, (SfaExperimentPart) experimentPart));
        }

        return null;
    }

    public class CreateImageState extends SingleCallState<CreateImageTask> {

        protected CreateImageState() {
            super("Create disk image from node " + nodeToImage.getClientId(),
                    hltf.createImage(experiment.getSlice(), nodeToImage.getSliverId(), imageName, global, updatePrepare));
        }

        @Nonnull
        @Override
        public ExperimentTaskStatus executeState(Job<?> job) throws InterruptedException {
            ExperimentTaskStatus result = super.executeState(job);

            updateMessage(task.getResultDiskImageUrn().toString());

            return result;
        }
    }
}
