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

import be.iminds.ilabt.jfed.rspec.model.ModelRspecType;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.*;
import be.iminds.ilabt.jfed.rspec.rspec_source.RequestRspecSource;
import javafx.scene.control.Alert;
import javafx.stage.Window;

import static javafx.scene.control.Alert.AlertType.ERROR;

/**
 * Checks whether all nodes/links/channels/routable pools have a component_manager_id
 * <p>
 * User: twalcari
 * Date: 1/22/2015
 * Time: 16:51
 */
public class HasComponentManagerIdsValidator implements RspecValidator {
    @Override
    public RspecValidationResult validateRSpec(RspecCheckReason reason, RequestRspecSource requestRspecSource, Window dialogOwner) {
        FXModelRspec modelRspec = requestRspecSource.getModelRspec(ModelRspecType.FX);
        assert (modelRspec != null);

        final boolean showAlert = reason != RspecCheckReason.OPENED_FILE && reason != RspecCheckReason.SWITCH_TO_VISUAL_EDITOR;

        boolean invalid = false;

        if (hasNodeWithNullComponentManagerId(modelRspec)) {
            if (showAlert)
                new Alert(ERROR, "One or more nodes do not have a component_manager_id. " +
                        "This is a mandatory field. thus the Rspec is invalid.").showAndWait();

            invalid = true;
        }

        if (hasLinkWithNullComponentManagerId(modelRspec)) {
            if (showAlert)
                new Alert(ERROR, "One or more links do not have a component_manager_id. " +
                        "This is a mandatory field. thus the Rspec is invalid.").showAndWait();

            invalid = true;
        }
        if (hasChannelWithNullComponentManagerId(modelRspec)) {
            if (showAlert)
                new Alert(ERROR, "One or more channels do not have a component_manager_id. " +
                        "This is a mandatory field. thus the Rspec is invalid.").showAndWait();

            invalid = true;
        }
        if (hasAddressPoolWithNullComponentManagerId(modelRspec)) {
            if (showAlert)
                new Alert(ERROR, "One or more address pools do not have a component_manager_id. " +
                        "This is a mandatory field. thus the Rspec is invalid.").showAndWait();

            invalid = true;
        }

        if (invalid) {
            switch (reason) {
                case RUN_EXPERIMENT:
                    return new RspecValidationResult(requestRspecSource, true);
                case SWITCH_TO_VISUAL_EDITOR: //fall-through
                case CHECK_RSPEC: //fall-through
                case OPENED_FILE:
                    return new RspecValidationResult(requestRspecSource, false/* == ignore*/);
                default:
                    throw new IllegalStateException("Unexpected reason");
            }
        } else
            return null;
    }

    private static boolean hasNodeWithNullComponentManagerId(FXModelRspec modelRspec) {
        for (FXRspecNode node : modelRspec.getNodes()) {
            if (node.getComponentManagerId() == null)
                return true;
        }
        return false;
    }

    private static boolean hasLinkWithNullComponentManagerId(FXModelRspec modelRspec) {
        for (FXRspecLink link : modelRspec.getLinks()) {
            if (link.getComponentManagerUrns().contains(null))
                return true;
        }
        return false;
    }

    private static boolean hasChannelWithNullComponentManagerId(FXModelRspec modelRspec) {
        for (FXRspecChannel channel : modelRspec.getChannels()) {
            if (channel.getComponentManagerId() == null)
                return true;
        }
        return false;
    }

    private static boolean hasAddressPoolWithNullComponentManagerId(FXModelRspec modelRspec) {
        for (FXAddressPool pool : modelRspec.getAddressPools()) {
            if (pool.getComponentManagerId() == null)
                return true;
        }
        return false;
    }
}
