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

import be.iminds.ilabt.jfed.highlevel.controller.JFedHighLevelException;
import be.iminds.ilabt.jfed.highlevel.controller.Task;
import be.iminds.ilabt.jfed.highlevel.controller.TaskExecution;
import be.iminds.ilabt.jfed.highlevel.model.SfaModel;
import be.iminds.ilabt.jfed.highlevel.model.Slice;
import be.iminds.ilabt.jfed.lowlevel.JFedException;
import be.iminds.ilabt.jfed.lowlevel.api_wrapper.UserAndSliceApiWrapper;
import be.iminds.ilabt.jfed.util.GeniUrn;
import be.iminds.ilabt.jfed.util.JavaFXLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.Instant;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * User: twalcari
 * Date: 6/17/2015
 * Time: 11:42
 */
public final class CreateSliceTask extends Task {
    private static final Logger LOG = LoggerFactory.getLogger(CreateSliceTask.class);

    //input parameters
    private final String sliceName;
    private final String subAuthority;
    private final Instant expirationDate;
    private Slice slice;

    //environment parameters
    private final UserAndSliceApiWrapper userAndSliceApiWrapper;
    private final JavaFXLogger logger;
    private final SfaModel sfaModel;
    private final HighLevelTaskFactory hltf;


    /**
     * subAuthority may be null (= no sub authority)
     */
    public CreateSliceTask(@Nonnull String sliceName, @Nullable String subAuthority,
                           UserAndSliceApiWrapper userAndSliceApiWrapper, JavaFXLogger logger,
                           SfaModel sfaModel, HighLevelTaskFactory hltf) {
        this(sliceName, subAuthority, null, userAndSliceApiWrapper, logger, sfaModel, hltf);
    }

    /**
     * subAuthority may be null (= no sub authority)
     */
    public CreateSliceTask(@Nonnull String sliceName, @Nullable String subAuthority, @Nullable Instant expirationDate,
                           UserAndSliceApiWrapper userAndSliceApiWrapper, JavaFXLogger logger,
                           SfaModel sfaModel, HighLevelTaskFactory hltf) {
        super("Create Slice");
        this.sliceName = sliceName;
        this.subAuthority = subAuthority;
        this.expirationDate = expirationDate;
        this.userAndSliceApiWrapper = userAndSliceApiWrapper;
        this.logger = logger;
        this.sfaModel = sfaModel;
        this.hltf = hltf;
    }

    @Override
    public void doTask(TaskExecution taskExecution) throws JFedException, InterruptedException {
        LOG.debug("Requesting slice with expiration time {}", expirationDate);

        assert userAndSliceApiWrapper.hasUserCredentials() : "There was no valid user credential available.";
        if (!userAndSliceApiWrapper.hasUserCredentials())
            LOG.warn("Register call saw that UserAndSliceApiWrapper does not have a valid credential. The call will most likely fail.");

        UserAndSliceApiWrapper.SliceInfo sliceInfo;

        sliceInfo =
                userAndSliceApiWrapper.createSlice(JavaFXLogger.wrap(logger, taskExecution), sliceName,
                        expirationDate != null ? Date.from(expirationDate) : null, subAuthority);

        GeniUrn sliceUrn = sliceInfo.getUrn();

        slice = sfaModel.getSlice(sliceUrn);
        if (slice == null) {
            LOG.error("failed: slice was not added to SfaModel sliceUrn={}", sliceUrn);
            throw new JFedHighLevelException("Creation of slice was successful, but Task FAILED because slice was not added to SfaModel. sliceUrn=" + sliceUrn);
        }
        LOG.debug("success: '{}'", sliceUrn.toString());
    }

    @Override
    public List<Task> initDependsOn() {
        return Collections.singletonList(hltf.getUserCredential());
    }

    public String getSliceName() {
        return sliceName;
    }

    public Slice getSlice() {
        return slice;
    }
}
