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 java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Abstract class for states which are sliced over ONLY the SfaExperimentParts of an Experiment
 *
 * User: twalcari
 * Date: 1/12/2016
 * Time: 17:06
 */
public abstract class SfaExperimentPartsSlicedState<JS extends ExperimentPartStateSlice<SfaExperimentPart>> extends SlicedState<JS> {

    private final Experiment experiment;
    Map<ExperimentPart, JS> experimentPartJobSlices = null;

    private final Collection<SfaExperimentPart> parts;

    protected SfaExperimentPartsSlicedState(String name, Experiment experiment) {
        this(name, experiment, null);
    }


    /**
     * Use this constructor if you only want to execute the action for certain experiment parts.
     */
    protected SfaExperimentPartsSlicedState(String name, Experiment experiment, Collection<SfaExperimentPart> experimentParts) {
        super(name);
        this.experiment = experiment;

        parts = experimentParts != null ? experimentParts :
                experiment.getParts().stream()
                        .filter(part -> part instanceof SfaExperimentPart)
                        .map(SfaExperimentPart.class::cast)
                        .collect(Collectors.toList());
    }

    private void initializeStateSlices() {
        experimentPartJobSlices = new HashMap<>();
        for (SfaExperimentPart experimentPart : parts) {
            JS jobSlice = createJobSlice(experimentPart);

            experimentPartJobSlices.put(experimentPart, jobSlice);
        }
    }


    @Override
    public synchronized final Collection<JS> getSlices() {
        if (experimentPartJobSlices == null) {
            initializeStateSlices();
        }

        return experimentPartJobSlices.values();
    }

    public abstract JS createJobSlice(SfaExperimentPart experimentPart);
}
