/*--------------------------------------------------------------*
  Copyright (C) 2006-2015 OpenSim Ltd.

  This file is distributed WITHOUT ANY WARRANTY. See the file
  'License' for details on this and other legal matters.
*--------------------------------------------------------------*/

package org.omnetpp.ned.editor.graph.parts.policies;

import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.IFigure;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.ReconnectRequest;
import org.omnetpp.figures.ConnectionFigure;
import org.omnetpp.ned.editor.graph.commands.CreateConnectionCommand;
import org.omnetpp.ned.editor.graph.commands.ReconnectCommand;
import org.omnetpp.ned.editor.graph.parts.ModuleEditPart;
import org.omnetpp.ned.model.ex.CompoundModuleElementEx;
import org.omnetpp.ned.model.ex.ConnectionElementEx;
import org.omnetpp.ned.model.interfaces.IConnectableElement;

/**
 * Handle all connection related requests for graphically represented nodes (compound and submodules)
 *
 * @author rhornig
 */
public class NedGraphicalNodeEditPolicy extends GraphicalNodeEditPolicy {

    // Used to give feedback during dragging
    @Override
    protected Connection createDummyConnection(Request req) {
        ConnectionFigure cf = new ConnectionFigure();
        cf.setArrowHeadEnabled(true);
        return cf;
    }

    /**
     * Feedback should be added to the scaled feedback layer.
     *
     * @see org.eclipse.gef.editpolicies.GraphicalEditPolicy#getFeedbackLayer()
     */
    @Override
    protected IFigure getFeedbackLayer() {
        return getLayer(LayerConstants.SCALED_FEEDBACK_LAYER);
    }


    /**
     * Returns either the module name or "" if the module is a compound
     */
    private static String getModuleNameForConnection(IConnectableElement connectable) {
        if (connectable instanceof CompoundModuleElementEx)
            return "";
        return connectable.getName();
    }

    // called during connection creation on the first click
    @Override
    protected Command getConnectionCreateCommand(CreateConnectionRequest request) {
        ConnectionElementEx conn = (ConnectionElementEx)request.getNewObject();
        conn.setSrcModule(getModuleNameForConnection(getGraphNodeModel()));
        CreateConnectionCommand command = new CreateConnectionCommand(conn, getModuleEditPart().getCompoundModulePart().getModel());
        request.setStartCommand(command);
        return command;
    }

    // called when clicked on the second node during connection creation
    @Override
    protected Command getConnectionCompleteCommand(CreateConnectionRequest request) {
        CreateConnectionCommand command = (CreateConnectionCommand)request.getStartCommand();
        command.getConnection().setDestModule(getModuleNameForConnection(getGraphNodeModel()));
        return command;
    }

    @Override
    protected Command getReconnectTargetCommand(ReconnectRequest request) {
        ModuleEditPart srcEP = (ModuleEditPart)request.getConnectionEditPart().getSource();
        ModuleEditPart targetEP = (ModuleEditPart)request.getTarget();
        // allow the reconnection only inside the same compound module
        if (srcEP.getCompoundModulePart() != targetEP.getCompoundModulePart())
            return UnexecutableCommand.INSTANCE;

        ConnectionElementEx conn = (ConnectionElementEx)request.getConnectionEditPart().getModel();
        ReconnectCommand command = new ReconnectCommand(conn, true);
        command.getTemplateConnection().setDestModule(getModuleNameForConnection(getGraphNodeModel()));
        return command;
    }

    @Override
    protected Command getReconnectSourceCommand(ReconnectRequest request) {
        ModuleEditPart targetEP = (ModuleEditPart)request.getConnectionEditPart().getTarget();
        ModuleEditPart srcEP = (ModuleEditPart)request.getTarget();
        // allow the reconnection only inside the same compound module
        if (srcEP.getCompoundModulePart() != targetEP.getCompoundModulePart())
            return UnexecutableCommand.INSTANCE;

        ConnectionElementEx conn = (ConnectionElementEx)request.getConnectionEditPart().getModel();
        ReconnectCommand command = new ReconnectCommand(conn, false);
        command.getTemplateConnection().setSrcModule(getModuleNameForConnection(getGraphNodeModel()));
        return command;
    }

    protected ModuleEditPart getModuleEditPart() {
        return (ModuleEditPart)getHost();
    }

    protected IConnectableElement getGraphNodeModel() {
        return (IConnectableElement)getHost().getModel();
    }
}