/*******************************************************************************
 * Copyright (c) 2003, 2005 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 API and implementation
 *******************************************************************************/
 
package org.eclipse.ui.navigator.resources.internal.actions;


import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommand;
import org.eclipse.ui.commands.ICommandManager;
import org.eclipse.ui.commands.IKeySequenceBinding;

/**
 * A quick menu actions provides support to assign short cuts to sub menus.
 * 
 * Derived from the class of the same name in the JDT internals.
 * 
 * 
 * <p>
 * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
 * part of a work in progress. There is a guarantee neither that this API will
 * work nor that it will remain the same. Please do not use this API without
 * consulting with the Platform/UI team.
 * </p>
 * @since 3.2
 */
public abstract class QuickMenuAction extends Action {

	private static final int CHAR_INDENT = 3;

	/**
	 * Creates a new quick menu action with the given command id.
	 * 
	 * @param commandId
	 *            the command id of the short cut used to open the sub menu
	 */
	public QuickMenuAction(String commandId) {
		setActionDefinitionId(commandId);
	}

	/**
	 * {@inheritDoc}
	 */
	public void run() {
		Display display = Display.getCurrent();
		if (display == null)
			return;
		Control focus = display.getFocusControl();
		if (focus == null || focus.isDisposed())
			return;

		MenuManager menu = new MenuManager();
		fillMenu(menu);
		final Menu widget = menu.createContextMenu(focus.getShell());
		Point location = computeMenuLocation(focus, widget);
		if (location == null)
			return;
		widget.setLocation(location);
		widget.setVisible(true);
		while (!widget.isDisposed() && widget.isVisible()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		if (!widget.isDisposed()) {
			widget.dispose();
		}
	}

	/**
	 * Hook to fill a menu manager with the items of the sub menu.
	 * 
	 * @param menu
	 *            the sub menu to fill
	 */
	protected abstract void fillMenu(IMenuManager menu);

	/**
	 * Returns the short cut assigned to the sub menu or <code>null</code> if no short cut is
	 * assigned.
	 * 
	 * @return the short cut as a human readable string or <code>null</code>
	 */
	public String getShortCutString() {
		final ICommandManager commandManager = PlatformUI.getWorkbench().getCommandSupport().getCommandManager();
		final ICommand command = commandManager.getCommand(getActionDefinitionId());
		if (command.isDefined()) {
			List l = command.getKeySequenceBindings();
			if (!l.isEmpty()) {
				IKeySequenceBinding binding = (IKeySequenceBinding) l.get(0);
				return binding.getKeySequence().format();
			}
		}
		return null;  
	}

	private Point computeMenuLocation(Control focus, Menu menu) {
		Point cursorLocation = focus.getDisplay().getCursorLocation();
		Rectangle clientArea = null;
		Point result = null;
		if (focus instanceof StyledText) {
			StyledText styledText = (StyledText) focus;
			clientArea = styledText.getClientArea();
			result = computeMenuLocation(styledText);
		} else if (focus instanceof Tree) {
			Tree tree = (Tree) focus;
			clientArea = tree.getClientArea();
			result = computeMenuLocation(tree);
		} else if (focus instanceof Table) {
			Table table = (Table) focus;
			clientArea = table.getClientArea();
			result = computeMenuLocation(table);
		}
		if (result == null) {
			result = focus.toControl(cursorLocation);
		}
		if (clientArea != null && !clientArea.contains(result)) {
			result = new Point(clientArea.x + clientArea.width / 2, clientArea.y + clientArea.height / 2);
		}
		Rectangle shellArea = focus.getShell().getClientArea();
		if (!shellArea.contains(focus.getShell().toControl(focus.toDisplay(result)))) {
			result = new Point(shellArea.x + shellArea.width / 2, shellArea.y + shellArea.height / 2);
		}
		return focus.toDisplay(result);
	}

	/**
	 * Hook to compute the menu location if the focus widget is a styled text widget.
	 * 
	 * @param text
	 *            the styled text widget that has the focus
	 * 
	 * @return a widget relative position of the menu to pop up or <code>null</code> if now
	 *         position inside the widget can be computed
	 */
	protected Point computeMenuLocation(StyledText text) {
		Point result = text.getLocationAtOffset(text.getCaretOffset());
		result.y += text.getLineHeight();
		if (!text.getClientArea().contains(result))
			return null;
		return result;
	}

	/**
	 * Hook to compute the menu location if the focus widget is a tree widget.
	 * 
	 * @param tree
	 *            the tree widget that has the focus
	 * 
	 * @return a widget relative position of the menu to pop up or <code>null</code> if now
	 *         position inside the widget can be computed
	 */
	protected Point computeMenuLocation(Tree tree) {
		TreeItem[] items = tree.getSelection();
		Rectangle clientArea = tree.getClientArea();
		switch (items.length) {
			case 0 :
				return null;
			case 1 :
				Rectangle bounds = items[0].getBounds();
				Rectangle intersect = clientArea.intersection(bounds);
				if (intersect != null && intersect.height == bounds.height) {
					return new Point(Math.max(0, bounds.x + getAvarageCharWith(tree) * CHAR_INDENT), bounds.y + bounds.height);
				}
				return null;

			default :
				Rectangle[] rectangles = new Rectangle[items.length];
				for (int i = 0; i < rectangles.length; i++) {
					rectangles[i] = items[i].getBounds();
				}
				Point cursorLocation = tree.getDisplay().getCursorLocation();
				Point result = findBestLocation(getIncludedPositions(rectangles, clientArea), tree.toControl(cursorLocation));
				if (result != null)
					result.x = result.x + getAvarageCharWith(tree) * CHAR_INDENT;
				return result;
		}
	}

	/**
	 * Hook to compute the menu location if the focus widget is a table widget.
	 * 
	 * @param table
	 *            the table widget that has the focus
	 * 
	 * @return a widget relative position of the menu to pop up or <code>null</code> if now
	 *         position inside the widget can be computed
	 */
	protected Point computeMenuLocation(Table table) {
		TableItem[] items = table.getSelection();
		Rectangle clientArea = table.getClientArea();
		switch (items.length) {
			case 0 : {
				return null;
			}
			case 1 : {
				Rectangle bounds = items[0].getBounds(0);
				Rectangle iBounds = items[0].getImageBounds(0);
				Rectangle intersect = clientArea.intersection(bounds);
				if (intersect != null && intersect.height == bounds.height) {
					return new Point(Math.max(0, bounds.x + iBounds.width + getAvarageCharWith(table) * CHAR_INDENT), bounds.y + bounds.height);
				}
				return null;

			}
			default : {
				Rectangle[] rectangles = new Rectangle[items.length];
				for (int i = 0; i < rectangles.length; i++) {
					rectangles[i] = items[i].getBounds(0);
				}
				Rectangle iBounds = items[0].getImageBounds(0);
				Point cursorLocation = table.getDisplay().getCursorLocation();
				Point result = findBestLocation(getIncludedPositions(rectangles, clientArea), table.toControl(cursorLocation));
				if (result != null)
					result.x = result.x + iBounds.width + getAvarageCharWith(table) * CHAR_INDENT;
				return result;
			}
		}
	}

	private Point[] getIncludedPositions(Rectangle[] rectangles, Rectangle widgetBounds) {
		List result = new ArrayList();
		for (int i = 0; i < rectangles.length; i++) {
			Rectangle rectangle = rectangles[i];
			Rectangle intersect = widgetBounds.intersection(rectangle);
			if (intersect != null && intersect.height == rectangle.height) {
				result.add(new Point(intersect.x, intersect.y + intersect.height));
			}
		}
		return (Point[]) result.toArray(new Point[result.size()]);
	}

	private Point findBestLocation(Point[] points, Point relativeCursor) {
		Point result = null;
		double bestDist = Double.MAX_VALUE;
		for (int i = 0; i < points.length; i++) {
			Point point = points[i];
			int a = 0;
			int b = 0;
			if (point.x > relativeCursor.x) {
				a = point.x - relativeCursor.x;
			} else {
				a = relativeCursor.x - point.x;
			}
			if (point.y > relativeCursor.y) {
				b = point.y - relativeCursor.y;
			} else {
				b = relativeCursor.y - point.y;
			}
			double dist = Math.sqrt(a * a + b * b);
			if (dist < bestDist) {
				result = point;
				bestDist = dist;
			}
		}
		return result;
	}

	private int getAvarageCharWith(Control control) {
		GC gc = null;
		try {
			gc = new GC(control);
			return gc.getFontMetrics().getAverageCharWidth();
		} finally {
			if (gc != null)
				gc.dispose();
		}
	}
}
