/**
 * File:    ReferenceEditPart.java
 * Created: 25.02.2006
 *
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * University of Augsburg, Germany <www.ds-lab.org>
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Markus Bauer, Programming distributed Systems Lab, University of Augsburg 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.parts.view;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.jwt.meta.model.core.GraphicalElement;
import org.eclipse.jwt.meta.model.core.PackageableElement;
import org.eclipse.jwt.we.editors.WEEditor;
import org.eclipse.jwt.we.misc.logging.Logger;
import org.eclipse.jwt.we.misc.util.GeneralHelper;
import org.eclipse.jwt.we.misc.views.Views;
import org.eclipse.jwt.we.model.view.Reference;
import org.eclipse.jwt.we.model.view.ViewPackage;
import org.eclipse.jwt.we.parts.core.GraphicalElementEditPartHelper;
import org.eclipse.jwt.we.parts.core.NodeModelElementEditPart;
import org.eclipse.jwt.we.parts.core.ReferenceableElementEditPart;
import org.eclipse.jwt.we.parts.core.ReferenceableElementProxyEditPart;
import org.eclipse.jwt.we.parts.processes.policies.DelegatingEditPolicy;
import org.eclipse.jwt.we.parts.view.policies.ReferenceGraphicalNodeEditPolicy;

/**
 * EditPart for a {@link Reference}.
 * 
 * @version $Id: ReferenceEditPart.java,v 1.4 2009-12-21 10:30:47 chsaad Exp $
 * @author Markus Bauer (markusbauer@users.sourceforge.net), Programming
 *         distributed Systems Lab, University of Augsburg, Germany,
 *         www.ds-lab.org
 * @since 0.6.0
 */
public class ReferenceEditPart extends NodeModelElementEditPart
{

	Logger logger = Logger.getLogger(ReferenceEditPart.class);

	/**
	 * Helper for functions from the GraphicalElement.
	 */
	private final GraphicalElementEditPartHelper graphicalElementEditPartHelper = new GraphicalElementEditPartHelper(
			this);


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jwt.we.parts.core.NamedElementEditPart#getModelClass()
	 */
	@Override
	public Class getModelClass()
	{
		return Reference.class;
	}


	/**
	 * @return The model element that is referenced.
	 */
	public PackageableElement getReference()
	{
		return ((Reference) getModel()).getReference();
	}


	/**
	 * @return The model casted to a {@link GraphicalElement}, or
	 *         <code>null</code> if it is not a GraphicalElement.
	 */
	public GraphicalElement getGraphicalElementModel()
	{
		return (GraphicalElement) super.getModel();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
	 */
	@Override
	protected List getModelChildren()
	{
		// the reference is the only child
		if (getReference() == null)
		{
			return Collections.EMPTY_LIST;
		}
		return Collections.singletonList(getReference());
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editparts.AbstractGraphicalEditPart#getModelTargetConnections
	 * ()
	 */
	@Override
	protected List getModelTargetConnections()
	{
		if (!Views.getInstance().displayObject(((EObject) this.getModel()).eClass()))
			return null;
		return ((Reference) getModel()).getReferenceEdges();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.eclipse.jwt.we.parts.core.GraphicalModelElementEditPart#
	 * createEditPolicies()
	 */
	@Override
	protected void createEditPolicies()
	{
		super.createEditPolicies();

		installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE,
				new ReferenceGraphicalNodeEditPolicy());

		// delegate all other request to the referenced element
		installEditPolicy(DelegatingEditPolicy.DELEGATING_ROLE,
				new DelegatingEditPolicy());
	}


	/**
	 * Creates the ConnectionAnchor for this EditPart.
	 * 
	 * Subclasses should overwrite this method, if they need a different anchor.
	 * 
	 * @return The connection anchor
	 */
	@Override
	protected ConnectionAnchor createConnectionAnchor()
	{
		return new ChopboxAnchor(getFigure());
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.jwt.we.parts.core.NamedElementEditPart#performRequest(org
	 * .eclipse.gef.Request)
	 */
	@Override
	public void performRequest(Request request)
	{
		// pass direct edit request to children
		if (request.getType() == RequestConstants.REQ_DIRECT_EDIT)
		{
			for (Iterator children = getChildren().iterator(); children.hasNext();)
			{
				((EditPart) children.next()).performRequest(request);
			}
		}
		else
		{
			super.performRequest(request);
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.jwt.we.parts.core.NamedElementEditPart#notifyChanged(org.
	 * eclipse.emf.common.notify.Notification)
	 */
	@Override
	public void notifyChanged(Notification notification)
	{
		// call super notify
		super.notifyChanged(notification);

		// call graphicalelement notify
		graphicalElementEditPartHelper.notifyChanged(notification);

		int featureId = notification.getFeatureID(Reference.class);

		switch (notification.getEventType())
		{
			case Notification.SET:
			case Notification.UNSET:
				switch (featureId)
				{
					case ViewPackage.REFERENCE__REFERENCE:
						refreshChildren();
						break;
				}
				break;

			case Notification.ADD:
			case Notification.ADD_MANY:
			case Notification.REMOVE:
			case Notification.REMOVE_MANY:
				switch (featureId)
				{
					case ViewPackage.REFERENCE__REFERENCE_EDGES:
						refreshTargetConnections();
						break;
				}
		}
	}


	/**
	 * The figure comes from an {@link ReferenceableElementProxyEditPart}
	 */
	@Override
	protected void addChild(EditPart child, int index)
	{
		super.addChild(new ReferenceableElementProxyEditPart(
				(ReferenceableElementEditPart) child), index);
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jwt.we.parts.core.NamedElementEditPart#refreshVisuals()
	 */
	@Override
	protected void refreshVisuals()
	{
		super.refreshVisuals();
		graphicalElementEditPartHelper.refreshVisuals();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.jwt.we.parts.core.GraphicalModelElementEditPart#getWEEditor()
	 */
	@Override
	public WEEditor getWEEditor()
	{
		if (weeditor == null)
		{
			weeditor = GeneralHelper.getInstanceForEObject((EObject) getReference());
		}

		return weeditor;
	}

}
