//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// 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:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.gef.edit;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.epf.authoring.gef.commands.ChangeNameCommand;
import org.eclipse.epf.authoring.gef.figures.Colors;
import org.eclipse.epf.authoring.gef.figures.SelectableLabel;
import org.eclipse.epf.authoring.gef.figures.TextFigure;
import org.eclipse.epf.authoring.gef.util.TemplateConstants;
import org.eclipse.epf.diagram.model.ModelPackage;
import org.eclipse.epf.diagram.model.NamedNode;
import org.eclipse.epf.diagram.model.Node;
import org.eclipse.epf.diagram.model.WorkBreakdownElementNode;
import org.eclipse.epf.diagram.model.WorkProductDescriptorNode;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.DirectEditPolicy;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.swt.graphics.Image;

import com.ibm.icu.text.BreakIterator;

/**
 * @author Phong Nguyen Le
 * @since 1.0
 */
public abstract class NamedNodeEditPart extends NodeEditPart {

	public NamedNodeEditPart(NamedNode model) {
		super(model);
	}

	protected IFigure createFigure() {
		Label l = new SelectableLabel();
		l.setLabelAlignment(PositionConstants.LEFT);
		if (getImage() != null) {
			l.setIcon(getImage());
		}
		l.setTextPlacement(PositionConstants.SOUTH);
		l.setFont(TemplateConstants.DEFAULT_FONT);
		setLabelForegroundColor(l);
		return l;
	}

	private void setLabelForegroundColor(Label l) {
		NamedNode node = (NamedNode) getModel();
		// Object e = node.getObject();
		// boolean suppressed = isSuppressed(e);
		boolean suppressed = node.isSuppressed();
		if (node.isReadOnly()) {
			if (!suppressed) {
				l.setForegroundColor(Colors.INHERITED_ELEMENT_LABEL);
			}
		} else {
			if (!suppressed) {
				l.setForegroundColor(ColorConstants.black);
			}
		}
		if (suppressed) {
			l.setForegroundColor(Colors.SUPRESSED_ELEMENT_LABEL);
		}
	}

	protected Image getImage() {
		return null;
	}

	protected void createEditPolicies() {
		super.createEditPolicies();
		if (!((Node) getModel()).isReadOnly()) {
			installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE,
					createDirectEditPolicy());
		}
	}

	protected DirectEditPolicy createDirectEditPolicy() {
		return new DirectEditPolicy() {
			protected Command getDirectEditCommand(DirectEditRequest request) {
				return new ChangeNameCommand((NamedNode) getModel(),
						(String) request.getCellEditor().getValue());
			}

			protected void showCurrentEditValue(DirectEditRequest request) {
				IFigure fig = getDirectEditFigure();
				String s = (String) request.getCellEditor().getValue();
				if (fig instanceof Label) {
					((Label) fig).setText(s);
				}
				else if (fig instanceof TextFigure) {
					((TextFigure) fig).setText(s);
				}
				fig.getUpdateManager().performUpdate();
			}
		};
	}

	protected void handlePropertyChanged(Notification msg) {
		switch (msg.getFeatureID(NamedNode.class)) {
		case ModelPackage.NAMED_NODE__NAME:
			refreshVisuals();
			return;
		}
		super.handlePropertyChanged(msg);
	}

	public void performRequest(Request request) {
		if (request.getType() == RequestConstants.REQ_DIRECT_EDIT
				&& !((Node) getModel()).isReadOnly()) {
			performDirectEdit();
		} else {
			super.performRequest(request);
		}
	}

	protected static final int WRAP_WIDTH = 12;

	protected static final int WORK_PRODUCT_WRAP_WIDTH = 3;

	protected void refreshVisuals() {
		super.refreshVisuals();
		IFigure fig = getDirectEditFigure();
		if (fig instanceof Label) {
			Label l = (Label) fig;
			setLabelForegroundColor(l);
			String text;
			// Below check is required for Extended Activity presentation name
			// should be used from base.
			if (getModel() instanceof WorkBreakdownElementNode) {
				WorkBreakdownElementNode node = (WorkBreakdownElementNode) getModel();
				Object wbelement = node.getObject();
				if (wbelement instanceof Activity
						&& ProcessUtil
								.isExtendingOrLocallyContributing((BreakdownElement) wbelement)) {
					text = ProcessUtil
							.getPresentationName((BreakdownElement) wbelement);
				} else {
					text = ((NamedNode) getModel()).getName();
				}
			} else {
				text = ((NamedNode) getModel()).getName();
			}
			try {
				if (getParent() instanceof ActivityDetailDiagramEditPart
						|| getParent().getParent() instanceof ActivityDetailDiagramEditPart) {
					int w = WRAP_WIDTH;
					if (this.getModel() instanceof WorkProductDescriptorNode)
						w = WORK_PRODUCT_WRAP_WIDTH;
					text = wrap(text, w);
				}
			} catch (NullPointerException npe) {
			}
			l.setText(text);
		}
	}

	protected String wrap(String s, int wrapWidth) {
		String wrapped = ""; //$NON-NLS-1$
		BreakIterator bi = BreakIterator.getLineInstance();
		String remaining = s;
		while (true) {
			if (remaining.length() <= wrapWidth) {
				wrapped += remaining;
				break;
			} else {
				bi.setText(remaining);
				int pos = bi.following(wrapWidth);
				if (pos == BreakIterator.DONE) {
					wrapped += remaining;
					break;
				} else {
					if (pos >= remaining.length()) {
						wrapped += remaining;
						break;
					} else {
						wrapped += remaining.substring(0, pos) + "\n"; //$NON-NLS-1$
						remaining = remaining.substring(pos);
					}
				}
			}
		}
		return wrapped;
	}

}