package be.iminds.ilabt.jfed.experimenter_gui.editor.actions;

import be.iminds.ilabt.jfed.experimenter_gui.dialogs.DialogsFactory;
import be.iminds.ilabt.jfed.experimenter_gui.editor.EditableRspec;

import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
import be.iminds.ilabt.jfed.lowlevel.authority.AuthorityFinder;
import be.iminds.ilabt.jfed.fedmon.webapi.service.json.*;
import be.iminds.ilabt.jfed.rspec.rspec_source.RequestRspecSource;
import be.iminds.ilabt.jfed.ui.javafx.dialogs.JFDialogs;
import be.iminds.ilabt.jfed.util.GeniUrn;
import javafx.stage.Window;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;
import java.util.stream.Collectors;

/**
 * User: twalcari
 * Date: 5/20/2015
 * Time: 09:15
 */
public class CreateReservationAction extends RspecValidatingEditorAction<Boolean> {
    private static final Logger LOG = LoggerFactory.getLogger(CreateReservationAction.class);

    private final DialogsFactory dialogsFactory;

    CreateReservationAction(EditableRspec editableRspec, Window parentWindow,
                                   EditorActionsFactory editorActionsFactory, TestbedInfoSource testbedInfoSource, AuthorityFinder authorityFinder, DialogsFactory dialogsFactory) {
        super(editableRspec, parentWindow, editorActionsFactory, testbedInfoSource, authorityFinder);
        this.dialogsFactory = dialogsFactory;
    }

    @Override
    public Boolean call() {
        if (!prepareAndValidateRequestRspec()) {
            LOG.debug("Reserving experiment aborted because validation failed");
            return false;
        }

        RequestRspecSource requestRspecSource = editableRspec.getRequestRspecSource();

        if (requestRspecSource.getAllComponentManagerUrns().isEmpty()) {
            JFDialogs.create()
                    .owner(parentWindow)
                    .message("jFed could not find component managers in the RSpec XML. " +
                            "Either there is an error in the RSpec, or jFed does not support this RSpec. " +
                            "Either way, it is impossible to continue, \"Run Experiment\" aborted.")
                    .masthead("Fatal Error")
                    .showError();
            return false;
        }
        Set<GeniUrn> unknownComponentManagerUrns = getUnkownComponentManagerUrns(requestRspecSource);
        if (!unknownComponentManagerUrns.isEmpty()) {
            String urns = unknownComponentManagerUrns.stream().map(GeniUrn::toString).collect(Collectors.joining(", "));

            JFDialogs.create()
                    .message("jFed does not have information about some component managers in the RSpec XML: " + urns + " \n" +
                            "It is impossible to correctly continue, \"Run Experiment\" aborted.")
                    .masthead("Fatal Error")
                    .showError();
            return false;
        }

        //make sure the RSpec only contains reservable resources
        Set<Server> unreservableComponentManagerUrns =
                requestRspecSource.getAllComponentManagerUrns().stream()
                        .map(urn -> authorityFinder.findByUrn(urn, AuthorityFinder.Purpose.CREATE_SLIVER))
                        .filter(auth -> !(auth.hasFlag(Server.Flag.featureReservationsGeni)
                                || auth.hasFlag(Server.Flag.featureReservationsNitos)))
                        .collect(Collectors.toSet());
        if (!unreservableComponentManagerUrns.isEmpty()) {

            JFDialogs.create()
                    .message("This RSpec contains resources that cannot be reserved in advance. Please remove all resources from the following authorities to continue: " +
                            unreservableComponentManagerUrns.stream().map(Server::getName).collect(Collectors.joining(", ")))
                    .masthead("Unsupported authorities detected")
                    .showError();

            return false;
        }


        dialogsFactory.showCreateReservationDialog(parentWindow, requestRspecSource);

        return true;
    }
}
