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.Slice;
import be.iminds.ilabt.jfed.lowlevel.GeniAMResponseCode;
import be.iminds.ilabt.jfed.lowlevel.JFedException;
import be.iminds.ilabt.jfed.lowlevel.api_wrapper.StatusDetails;
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 java.util.Collections;
import java.util.List;

/**
 * User: twalcari
 * Date: 6/16/2015
 * Time: 16:15
 */
public class SliceCredentialTask extends Task {
    private static final Logger LOG = LoggerFactory.getLogger(SliceCredentialTask.class);

    //input arguments
    private final Slice slice;

    //environment arguments
    private final UserAndSliceApiWrapper userAndSliceApiWrapper;
    private final JavaFXLogger logger;
    private final HighLevelTaskFactory highLevelTaskFactory;


    SliceCredentialTask(@Nonnull Slice slice, UserAndSliceApiWrapper userAndSliceApiWrapper, JavaFXLogger logger,
                        HighLevelTaskFactory highLevelTaskFactory) {
        super("Get Slice Credential " + slice.getUrn());
        this.slice = slice;

        this.userAndSliceApiWrapper = userAndSliceApiWrapper;
        this.logger = logger;
        this.highLevelTaskFactory = highLevelTaskFactory;
    }


    @Override
    public void doTask(TaskExecution taskExecution) throws JFedException, InterruptedException {
        try {
            userAndSliceApiWrapper.getSliceCredentials(JavaFXLogger.wrap(true/*synchronous*/, logger, taskExecution), GeniUrn.parse(slice.getUrnString()));
        } catch (JFedException ex) {
            if (ex.getXmlRpcReply() != null
                    && ex.getXmlRpcReply().getGeniResponseCode() == GeniAMResponseCode.GENIRESPONSE_SEARCHFAILED) {
                //the slice, and it's sliver do not exist anymore!

                slice.getSlivers().stream()
                        .filter(sliver -> sliver.getStatus().getGlobalStatus() != StatusDetails.SliverStatus.FAIL)
                        .forEach(sliver -> sliver.setStatus(new StatusDetails(StatusDetails.SliverStatus.UNALLOCATED)));
            }

            throw ex;
        }


        //assert slice.hasCredential() : "resulting credential was NOT registered with SfaModel!";
        if (!slice.hasCredential())
            throw new JFedHighLevelException("Error processing reply: No valid slice credential was found");

        if (slice.isExpired()) {
            //the slice, and it's sliver do not exist anymore!

            slice.getSlivers().stream()
                    .filter(sliver -> sliver.getStatus().getGlobalStatus() != StatusDetails.SliverStatus.FAIL)
                    .forEach(sliver -> sliver.setStatus(new StatusDetails(StatusDetails.SliverStatus.UNALLOCATED)));

            throw new JFedHighLevelException("Error processing reply: got credential for expired slice");
        }
    }

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

    @Override
    public boolean newExecutionNeeded() {
        if (slice.isExpired()) {
            LOG.warn("Slice " + slice.getUrnString() + " has expired, so a new execution of Get Slice Credential is needed.");
            return true;
        }

        //TODO also check whether slice credential hasn't expired  (somewhat pointless: slice credential expires is same as slice expire...)

        return !slice.hasCredential();
    }
}
