package be.iminds.jfed.gts_highlevel.jobs.gts_parts;

import be.iminds.ilabt.jfed.experiment.Experiment;
import be.iminds.ilabt.jfed.highlevel.jobs.ExperimentPartStateSlice;
import be.iminds.ilabt.jfed.highlevel.jobs.Job;
import be.iminds.ilabt.jfed.highlevel.jobs.StateSlice;
import be.iminds.ilabt.jfed.highlevel.jobs.parts.NonSfaExperimentPartController;
import be.iminds.ilabt.jfed.lowlevel.api.user_spec.UserSpec;
import be.iminds.ilabt.jfed.rspec.model.ModelRspecType;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXGeantTestbedType;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXModelRspec;
import be.iminds.jfed.gts_highlevel.controller.GtsModel;
import be.iminds.jfed.gts_highlevel.tasks.GtsTaskFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import javax.inject.Inject;
import java.time.Instant;
import java.util.Collection;

/**
 * User: twalcari
 * Date: 1/12/2016
 * Time: 17:31
 */
public class GtsExperimentPartController implements NonSfaExperimentPartController<GtsExperimentPart, GtsExperimentPartsContainer> {
    private static final Logger LOG = LoggerFactory.getLogger(GtsExperimentPartController.class);

    private final GtsModel model;
    private final GtsTaskFactory gtsTaskFactory;

    @Inject
    public GtsExperimentPartController(GtsModel model, GtsTaskFactory gtsTaskFactory) {
        this.model = model;
        this.gtsTaskFactory = gtsTaskFactory;
    }

    @Override
    public boolean supportsEditSshKeys(GtsExperimentPart experimentPart) {
        return false;
    }


    @Override
    public ExperimentPartStateSlice<GtsExperimentPart> editSshKeys(Job<?> job, GtsExperimentPart experimentPart, Collection<UserSpec> userSpecs) {
        throw new UnsupportedOperationException("GTS has not support for editing SSH keys");
    }

    @Override
    public boolean supportsRestore(GtsExperimentPart experimentPart) {
        return false;
    }

    @Override
    public ExperimentPartStateSlice<GtsExperimentPart> restore(Job<?> job, GtsExperimentPart experimentPart) {
        throw new UnsupportedOperationException("GTS has no support for restoring");
    }

    @Override
    public boolean supportsRenew(GtsExperimentPart experimentPart) {
        return false;
    }


    @Override
    public ExperimentPartStateSlice<GtsExperimentPart> renew(Job<?> job, GtsExperimentPart experimentPart, Instant newExpirationTime) {
        throw new UnsupportedOperationException("Currently no GTS support for renewing resources");
    }


    @Nullable
    @Override
    public StateSlice initializeContainer(Job<?> job) {
        return new InitializeGtsProjectStateSlice(job, model, gtsTaskFactory);
    }

    @Nullable
    @Override
    public StateSlice destroyContainer(Job<?> job, GtsExperimentPartsContainer container) {

        return new DestroyGtsProjectStateSlice(job, container, gtsTaskFactory);
    }

    @Nullable
    @Override
    public Class<GtsExperimentPartsContainer> getContainerClass() {
        return GtsExperimentPartsContainer.class;
    }

    @Override
    public void populateExperimentParts(Experiment experiment) {
        if (experiment.getNewRequestRspecSource() == null)
            return;

        FXModelRspec modelRspec = experiment.getNewRequestRspecSource().getModelRspec(ModelRspecType.FX);

        if (modelRspec == null)
            return;

        for (FXGeantTestbedType geantTestbedType : modelRspec.getGeantTestbedTypes()) {
            experiment.getParts().add(new GtsExperimentPart(experiment, geantTestbedType, model));
        }

    }

    @Override
    public ExperimentPartStateSlice<GtsExperimentPart> start(Job<?> job, GtsExperimentPart experimentPart) {
        return new StartGtsExperimentPartStateSlice(job, experimentPart, model, gtsTaskFactory);
    }

    @Override
    public ExperimentPartStateSlice<GtsExperimentPart> update(Job<?> job, GtsExperimentPart experimentPart) {
        return new UpdateGtsExperimentPartStateSlice(job, experimentPart, gtsTaskFactory);
    }

    @Override
    public ExperimentPartStateSlice<GtsExperimentPart> stop(Job<?> job, GtsExperimentPart experimentPart) {
        return new StopGtsExperimentPartStateSlice(job, experimentPart, gtsTaskFactory);
    }
}
