package be.iminds.ilabt.jfed.experiment;

/**
 * User: twalcari
 * Date: 1/30/2015
 * Time: 11:05
 */
public enum ExperimentState {

    /**
     * Initial status of a new Experiment.
     * <p/>
     * The slice is to be created at the slice authority (It is currently unallocated).
     * <p/>
     * Next step in lifecycle will be @link{CREATED}
     */
    PENDING,

    /**
     * Initial status of an existing slice, of which we know nothing except for it's URN.
     * <p/>
     * While in this state, basic information about the slice is reconstructed by contacting the slice authority.
     * After that, all necessary sources are contacted to reconstruct the full state of all the slivers.
     * <p/>
     * When all sources have replied, the slice will transfer to the state @link{CREATED}
     */
    RESTORING,

    /**
     * The slice is allocated, but no resources have been requested (eg. allocated and provisioned).
     * <p/>
     * If we are expected to do request new resources (e.g. experiment.getNewRequestRspecSource() != null) then:
     * - if the resources are only available in the future: transfer to {@link #FUTURE_RESERVATION}
     * - otherwise, transfer to {@link #ALLOCATING}
     * <p/>
     * If we don't have to request any new resources, we can directly transfer to {@link #TESTING} the existing resources
     */
    CREATED,


    /**
     * The resources mentioned in experiment.getNewRequestRespecSource() need to be allocated.
     * Only when the allocation was succesful, we can formally provision them.
     *
     * When the allocation request was succesful, we change the state to {@link #PROVISIONING} if the resources are
     * available immediately, or to {@link #FUTURE_RESERVATION} if we need to wait for the reservation to begin.
     */
    ALLOCATING,

    /**
     * The resources of the slice are not yet provisionable, we have to wait until the correct time arrives.
     * <p/>
     * Once the reservation start time passes, the slice can transfer to PROVISIONING.
     * <p/>
     * The slice contains a manifest of the resources it has been promised.
     */
    FUTURE_RESERVATION,

    /**
     * The resources of the slice are currently being provisioned.
     * During this status, the slice receives the manifests of all slivers.
     * <p/>
     * When provisioning is done, the resources must be tested (transfer to status READY).
     */
    PROVISIONING,

    /**
     * All resources present should be tested if they are available.
     * <p/>
     * This state will only be set when restoring a slice.
     */
    TESTING,

    /**
     * The slice is fully provisioned and tested.
     * <p/>
     * The slice remains in this state, until the expiration time of one or more resources is reached.
     * After that, it moves to the state EXPIRING, in which this is checked.
     * <p/>
     * If all resources have expired, the experiment changes to {@link #EXPIRED} or {@link #EMPTY}.
     * Otherwise, it returns to READY.
     */
    READY,

    /**
     * User requested to stop all resources in the experiment.
     */
    DELETING,

    /**
     * One or more slivers and/or slice is expiring. We need to check it to make sure it really happened!
     */
    EXPIRING,
    /**
     * All resources of the slice have expired
     */
    EXPIRED,

    /**
     * There are no more active resources in the experiment
     */
    EMPTY,

    /**
     * If a fatal error occurs, and the user should be asked if he wants to delete the resources, the ExperimentState transfers to failing.
     * After asking the user, and deleting the resources (if the user agreed to it), the state transfers to {@link #FAILED}
     */
    FAILING,

    /**
     * If there occurs a fatal error, the slice transfers to FAILED. The user cannot use this slice anymore.
     */
    FAILED;

    public boolean isTerminated() {
        return this == DELETING || this == EMPTY || this == EXPIRED;
    }

    public boolean isActiveState(){
        return this != FAILING && this != FAILED && this != EMPTY && this != EXPIRED;
    }
}
