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

import be.iminds.ilabt.jfed.experimenter_gui.editor.EditableRspec;
import be.iminds.ilabt.jfed.experimenter_gui.editor.rspec_validation.RspecCheckReason;
import be.iminds.ilabt.jfed.experimenter_gui.editor.rspec_validation.RspecValidationEngine;
import be.iminds.ilabt.jfed.experimenter_gui.editor.rspec_validation.RspecValidationResult;

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.util.GeniUrn;
import javafx.stage.Window;

import java.util.HashSet;
import java.util.Set;

/**
 * User: twalcari
 * Date: 5/20/2015
 * Time: 14:41
 */
public abstract class RspecValidatingEditorAction<T> extends EditorAction<T> {
    private final RspecValidationEngine validationEngine = new RspecValidationEngine();

    protected final EditorActionsFactory editorActionsFactory;
    protected final AuthorityFinder authorityFinder;
    protected final TestbedInfoSource testbedInfoSource;

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

    protected boolean prepareAndValidateRequestRspec(){
        RequestRspecSource requestRspecSource = editableRspec.getRequestRspecSource();

        RspecValidationResult verifyRspecResult =
                validationEngine.validateRSpec(RspecCheckReason.RUN_EXPERIMENT, requestRspecSource, parentWindow);
        if (verifyRspecResult != null) {

            if (verifyRspecResult.isAbort()) {
                //user aborted (and is aware of that already so no need show dialog)
                return false;
            }

            editableRspec.setRequestRspecSource(verifyRspecResult.getReplacementRequestRspecSource());
        }

        ProcessUnboundNodesAction processUnboundNodesAction =
                editorActionsFactory.createProcessUnboundNodesAction(editableRspec, parentWindow);

        return processUnboundNodesAction.call();
    }


    protected Set<GeniUrn> getUnkownComponentManagerUrns(RequestRspecSource requestRspecSource) {
        Set<GeniUrn> unknownComponentManagerUrns = new HashSet<>();
        for (GeniUrn componentManagerUrn : requestRspecSource.getAllComponentManagerUrns()) {
            Server auth =
                    authorityFinder.findByUrn(componentManagerUrn, AuthorityFinder.Purpose.CREATE_SLIVER);
            if (auth == null) {
                unknownComponentManagerUrns.add(componentManagerUrn);
            }
        }
        return unknownComponentManagerUrns;
    }
}
