/*******************************************************************************
 * Copyright (c) 2006, 2008 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:
 *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
 *                                                 bugfix in: 195137, 198089, 225190
 *******************************************************************************/

package org.eclipse.jface.window;

import java.util.HashMap;

import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;

/**
 * This class gives implementors to provide customized tooltips for any control.
 * 
 * @since 3.3
 */
public abstract class ToolTip {
	private Control control;

	private int xShift = 3;

	private int yShift = 0;

	private int popupDelay = 0;

	private int hideDelay = 0;

	private ToolTipOwnerControlListener listener;

	private HashMap data;

	// Ensure that only one tooltip is active in time
	private static Shell CURRENT_TOOLTIP;

	/**
	 * Recreate the tooltip on every mouse move
	 */
	public static final int RECREATE = 1;

	/**
	 * Don't recreate the tooltip as long the mouse doesn't leave the area
	 * triggering the tooltip creation
	 */
	public static final int NO_RECREATE = 1 << 1;

	private TooltipHideListener hideListener = new TooltipHideListener();

	private Listener shellListener;

	private boolean hideOnMouseDown = true;

	private boolean respectDisplayBounds = true;

	private boolean respectMonitorBounds = true;

	private int style;

	private Object currentArea;

	private static final boolean IS_OSX = Util.isCarbon();

	/**
	 * Create new instance which add TooltipSupport to the widget
	 * 
	 * @param control
	 *            the control on whose action the tooltip is shown
	 */
	public ToolTip(Control control) {
		this(control, RECREATE, false);
	}

	/**
	 * @param control
	 *            the control to which the tooltip is bound
	 * @param style
	 *            style passed to control tooltip behavior
	 * 
	 * @param manualActivation
	 *            <code>true</code> if the activation is done manually using
	 *            {@link #show(Point)}
	 * @see #RECREATE
	 * @see #NO_RECREATE
	 */
	public ToolTip(Control control, int style, boolean manualActivation) {
		this.control = control;
		this.style = style;
		this.control.addDisposeListener(new DisposeListener() {

			public void widgetDisposed(DisposeEvent e) {
				data = null;
				deactivate();
			}

		});

		this.listener = new ToolTipOwnerControlListener();
		this.shellListener = new Listener() {
			public void handleEvent(final Event event) {
				if (ToolTip.this.control != null
						&& !ToolTip.this.control.isDisposed()) {
					ToolTip.this.control.getDisplay().asyncExec(new Runnable() {

						public void run() {
							// Check if the new active shell is the tooltip
							// itself
							if (ToolTip.this.control.getDisplay()
									.getActiveShell() != CURRENT_TOOLTIP) {
								toolTipHide(CURRENT_TOOLTIP, event);
							}
						}

					});
				}
			}
		};

		if (!manualActivation) {
			activate();
		}
	}

	/**
	 * Restore arbitrary data under the given key
	 * 
	 * @param key
	 *            the key
	 * @param value
	 *            the value
	 */
	public void setData(String key, Object value) {
		if (data == null) {
			data = new HashMap();
		}
		data.put(key, value);
	}

	/**
	 * Get the data restored under the key
	 * 
	 * @param key
	 *            the key
	 * @return data or <code>null</code> if no entry is restored under the key
	 */
	public Object getData(String key) {
		if (data != null) {
			return data.get(key);
		}
		return null;
	}

	/**
	 * Set the shift (from the mouse position triggered the event) used to
	 * display the tooltip.
	 * <p>
	 * By default the tooltip is shifted 3 pixels to the right.
	 * </p>
	 * 
	 * @param p
	 *            the new shift
	 */
	public void setShift(Point p) {
		xShift = p.x;
		yShift = p.y;
	}

	/**
	 * Activate tooltip support for this control
	 */
	public void activate() {
		deactivate();
		control.addListener(SWT.Dispose, listener);
		control.addListener(SWT.MouseHover, listener);
		control.addListener(SWT.MouseMove, listener);
		control.addListener(SWT.MouseExit, listener);
		control.addListener(SWT.MouseDown, listener);
		control.addListener(SWT.MouseWheel, listener);
	}

	/**
	 * Deactivate tooltip support for the underlying control
	 */
	public void deactivate() {
		control.removeListener(SWT.Dispose, listener);
		control.removeListener(SWT.MouseHover, listener);
		control.removeListener(SWT.MouseMove, listener);
		control.removeListener(SWT.MouseExit, listener);
		control.removeListener(SWT.MouseDown, listener);
		control.removeListener(SWT.MouseWheel, listener);
	}

	/**
	 * Return whether the tooltip respects bounds of the display.
	 * 
	 * @return <code>true</code> if the tooltip respects bounds of the display
	 */
	public boolean isRespectDisplayBounds() {
		return respectDisplayBounds;
	}

	/**
	 * Set to <code>false</code> if display bounds should not be respected or
	 * to <code>true</code> if the tooltip is should repositioned to not
	 * overlap the display bounds.
	 * <p>
	 * Default is <code>true</code>
	 * </p>
	 * 
	 * @param respectDisplayBounds
	 */
	public void setRespectDisplayBounds(boolean respectDisplayBounds) {
		this.respectDisplayBounds = respectDisplayBounds;
	}

	/**
	 * Return whether the tooltip respects bounds of the monitor.
	 * 
	 * @return <code>true</code> if tooltip respects the bounds of the monitor
	 */
	public boolean isRespectMonitorBounds() {
		return respectMonitorBounds;
	}

	/**
	 * Set to <code>false</code> if monitor bounds should not be respected or
	 * to <code>true</code> if the tooltip is should repositioned to not
	 * overlap the monitors bounds. The monitor the tooltip belongs to is the
	 * same is control's monitor the tooltip is shown for.
	 * <p>
	 * Default is <code>true</code>
	 * </p>
	 * 
	 * @param respectMonitorBounds
	 */
	public void setRespectMonitorBounds(boolean respectMonitorBounds) {
		this.respectMonitorBounds = respectMonitorBounds;
	}

	/**
	 * Should the tooltip displayed because of the given event.
	 * <p>
	 * <b>Subclasses may overwrite this to get custom behavior</b>
	 * </p>
	 * 
	 * @param event
	 *            the event
	 * @return <code>true</code> if tooltip should be displayed
	 */
	protected boolean shouldCreateToolTip(Event event) {
		if ((style & NO_RECREATE) != 0) {
			Object tmp = getToolTipArea(event);

			// No new area close the current tooltip
			if (tmp == null) {
				hide();
				return false;
			}

			boolean rv = !tmp.equals(currentArea);
			return rv;
		}

		return true;
	}

	/**
	 * This method is called before the tooltip is hidden
	 * 
	 * @param event
	 *            the event trying to hide the tooltip
	 * @return <code>true</code> if the tooltip should be hidden
	 */
	private boolean shouldHideToolTip(Event event) {
		if (event != null && event.type == SWT.MouseMove
				&& (style & NO_RECREATE) != 0) {
			Object tmp = getToolTipArea(event);

			// No new area close the current tooltip
			if (tmp == null) {
				hide();
				return false;
			}

			boolean rv = !tmp.equals(currentArea);
			return rv;
		}

		return true;
	}

	/**
	 * This method is called to check for which area the tooltip is
	 * created/hidden for. In case of {@link #NO_RECREATE} this is used to
	 * decide if the tooltip is hidden recreated.
	 * 
	 * <code>By the default it is the widget the tooltip is created for but could be any object. To decide if
	 * the area changed the {@link Object#equals(Object)} method is used.</code>
	 * 
	 * @param event
	 *            the event
	 * @return the area responsible for the tooltip creation or
	 *         <code>null</code> this could be any object describing the area
	 *         (e.g. the {@link Control} onto which the tooltip is bound to, a
	 *         part of this area e.g. for {@link ColumnViewer} this could be a
	 *         {@link ViewerCell})
	 */
	protected Object getToolTipArea(Event event) {
		return control;
	}

	/**
	 * Start up the tooltip programmatically
	 * 
	 * @param location
	 *            the location relative to the control the tooltip is shown
	 */
	public void show(Point location) {
		Event event = new Event();
		event.x = location.x;
		event.y = location.y;
		event.widget = control;
		toolTipCreate(event);
	}

	private Shell toolTipCreate(final Event event) {
		if (shouldCreateToolTip(event)) {
			Shell shell = new Shell(control.getShell(), SWT.ON_TOP | SWT.TOOL
					| SWT.NO_FOCUS);
			shell.setLayout(new FillLayout());

			toolTipOpen(shell, event);

			return shell;
		}

		return null;
	}

	private void toolTipShow(Shell tip, Event event) {
		if (!tip.isDisposed()) {
			currentArea = getToolTipArea(event);
			createToolTipContentArea(event, tip);
			if (isHideOnMouseDown()) {
				toolTipHookBothRecursively(tip);
			} else {
				toolTipHookByTypeRecursively(tip, true, SWT.MouseExit);
			}

			tip.pack();
			Point size = tip.getSize();
			Point location = fixupDisplayBounds(size, getLocation(size, event));

			// Need to adjust a bit more if the mouse cursor.y == tip.y and
			// the cursor.x is inside the tip
			Point cursorLocation = tip.getDisplay().getCursorLocation();

			if (cursorLocation.y == location.y && location.x < cursorLocation.x
					&& location.x + size.x > cursorLocation.x) {
				location.y -= 2;
			}

			tip.setLocation(location);
			tip.setVisible(true);
		}
	}

	private Point fixupDisplayBounds(Point tipSize, Point location) {
		if (respectDisplayBounds || respectMonitorBounds) {
			Rectangle bounds;
			Point rightBounds = new Point(tipSize.x + location.x, tipSize.y
					+ location.y);

			Monitor[] ms = control.getDisplay().getMonitors();

			if (respectMonitorBounds && ms.length > 1) {
				// By default present in the monitor of the control
				bounds = control.getMonitor().getBounds();
				Point p = new Point(location.x, location.y);

				// Search on which monitor the event occurred
				Rectangle tmp;
				for (int i = 0; i < ms.length; i++) {
					tmp = ms[i].getBounds();
					if (tmp.contains(p)) {
						bounds = tmp;
						break;
					}
				}

			} else {
				bounds = control.getDisplay().getBounds();
			}

			if (!(bounds.contains(location) && bounds.contains(rightBounds))) {
				if (rightBounds.x > bounds.x + bounds.width) {
					location.x -= rightBounds.x - (bounds.x + bounds.width);
				}

				if (rightBounds.y > bounds.y + bounds.height) {
					location.y -= rightBounds.y - (bounds.y + bounds.height);
				}

				if (location.x < bounds.x) {
					location.x = bounds.x;
				}

				if (location.y < bounds.y) {
					location.y = bounds.y;
				}
			}
		}

		return location;
	}

	/**
	 * Get the display relative location where the tooltip is displayed.
	 * Subclasses may overwrite to implement custom positioning.
	 * 
	 * @param tipSize
	 *            the size of the tooltip to be shown
	 * @param event
	 *            the event triggered showing the tooltip
	 * @return the absolute position on the display
	 */
	public Point getLocation(Point tipSize, Event event) {
		return control.toDisplay(event.x + xShift, event.y + yShift);
	}

	private void toolTipHide(Shell tip, Event event) {
		if (tip != null && !tip.isDisposed() && shouldHideToolTip(event)) {
			control.getShell().removeListener(SWT.Deactivate, shellListener);
			currentArea = null;
			passOnEvent(tip, event);
			tip.dispose();
			CURRENT_TOOLTIP = null;
			afterHideToolTip(event);
		}
	}

	private void passOnEvent(Shell tip, Event event) {
		if (control != null && !control.isDisposed() && event != null
				&& event.widget != control && event.type == SWT.MouseDown) {
			final Display display = control.getDisplay();
			Point newPt = display.map(tip, null, new Point(event.x, event.y));

			final Event newEvent = new Event();
			newEvent.button = event.button;
			newEvent.character = event.character;
			newEvent.count = event.count;
			newEvent.data = event.data;
			newEvent.detail = event.detail;
			newEvent.display = event.display;
			newEvent.doit = event.doit;
			newEvent.end = event.end;
			newEvent.gc = event.gc;
			newEvent.height = event.height;
			newEvent.index = event.index;
			newEvent.item = event.item;
			newEvent.keyCode = event.keyCode;
			newEvent.start = event.start;
			newEvent.stateMask = event.stateMask;
			newEvent.text = event.text;
			newEvent.time = event.time;
			newEvent.type = event.type;
			newEvent.widget = event.widget;
			newEvent.width = event.width;
			newEvent.x = newPt.x;
			newEvent.y = newPt.y;

			tip.close();
			display.asyncExec(new Runnable() {
				public void run() {
					if (IS_OSX) {
						try {
							Thread.sleep(300);
						} catch (InterruptedException e) {

						}

						display.post(newEvent);
						newEvent.type = SWT.MouseUp;
						display.post(newEvent);
					} else {
						display.post(newEvent);
					}
				}
			});
		}
	}

	private void toolTipOpen(final Shell shell, final Event event) {
		// Ensure that only one Tooltip is shown in time
		if (CURRENT_TOOLTIP != null) {
			toolTipHide(CURRENT_TOOLTIP, null);
		}

		CURRENT_TOOLTIP = shell;

		control.getShell().addListener(SWT.Deactivate, shellListener);

		if (popupDelay > 0) {
			control.getDisplay().timerExec(popupDelay, new Runnable() {
				public void run() {
					toolTipShow(shell, event);
				}
			});
		} else {
			toolTipShow(CURRENT_TOOLTIP, event);
		}

		if (hideDelay > 0) {
			control.getDisplay().timerExec(popupDelay + hideDelay,
					new Runnable() {

						public void run() {
							toolTipHide(shell, null);
						}
					});
		}
	}

	private void toolTipHookByTypeRecursively(Control c, boolean add, int type) {
		if (add) {
			c.addListener(type, hideListener);
		} else {
			c.removeListener(type, hideListener);
		}

		if (c instanceof Composite) {
			Control[] children = ((Composite) c).getChildren();
			for (int i = 0; i < children.length; i++) {
				toolTipHookByTypeRecursively(children[i], add, type);
			}
		}
	}

	private void toolTipHookBothRecursively(Control c) {
		c.addListener(SWT.MouseDown, hideListener);
		c.addListener(SWT.MouseExit, hideListener);

		if (c instanceof Composite) {
			Control[] children = ((Composite) c).getChildren();
			for (int i = 0; i < children.length; i++) {
				toolTipHookBothRecursively(children[i]);
			}
		}
	}

	/**
	 * Creates the content area of the the tooltip.
	 * 
	 * @param event
	 *            the event that triggered the activation of the tooltip
	 * @param parent
	 *            the parent of the content area
	 * @return the content area created
	 */
	protected abstract Composite createToolTipContentArea(Event event,
			Composite parent);

	/**
	 * This method is called after a tooltip is hidden.
	 * <p>
	 * <b>Subclasses may override to clean up requested system resources</b>
	 * </p>
	 * 
	 * @param event
	 *            event triggered the hiding action (may be <code>null</code>
	 *            if event wasn't triggered by user actions directly)
	 */
	protected void afterHideToolTip(Event event) {

	}

	/**
	 * Set the hide delay.
	 * 
	 * @param hideDelay
	 *            the delay before the tooltip is hidden. If <code>0</code>
	 *            the tooltip is shown until user moves to other item
	 */
	public void setHideDelay(int hideDelay) {
		this.hideDelay = hideDelay;
	}

	/**
	 * Set the popup delay.
	 * 
	 * @param popupDelay
	 *            the delay before the tooltip is shown to the user. If
	 *            <code>0</code> the tooltip is shown immediately
	 */
	public void setPopupDelay(int popupDelay) {
		this.popupDelay = popupDelay;
	}

	/**
	 * Return if hiding on mouse down is set.
	 * 
	 * @return <code>true</code> if hiding on mouse down in the tool tip is on
	 */
	public boolean isHideOnMouseDown() {
		return hideOnMouseDown;
	}

	/**
	 * If you don't want the tool tip to be hidden when the user clicks inside
	 * the tool tip set this to <code>false</code>. You maybe also need to
	 * hide the tool tip yourself depending on what you do after clicking in the
	 * tooltip (e.g. if you open a new {@link Shell})
	 * 
	 * @param hideOnMouseDown
	 *            flag to indicate of tooltip is hidden automatically on mouse
	 *            down inside the tool tip
	 */
	public void setHideOnMouseDown(final boolean hideOnMouseDown) {
		// Only needed if there's currently a tooltip active
		if (CURRENT_TOOLTIP != null && !CURRENT_TOOLTIP.isDisposed()) {
			// Only change if value really changed
			if (hideOnMouseDown != this.hideOnMouseDown) {
				control.getDisplay().syncExec(new Runnable() {

					public void run() {
						if (CURRENT_TOOLTIP != null
								&& CURRENT_TOOLTIP.isDisposed()) {
							toolTipHookByTypeRecursively(CURRENT_TOOLTIP,
									hideOnMouseDown, SWT.MouseDown);
						}
					}

				});
			}
		}

		this.hideOnMouseDown = hideOnMouseDown;
	}

	/**
	 * Hide the currently active tool tip
	 */
	public void hide() {
		toolTipHide(CURRENT_TOOLTIP, null);
	}

	private class ToolTipOwnerControlListener implements Listener {
		public void handleEvent(Event event) {
			switch (event.type) {
			case SWT.Dispose:
			case SWT.KeyDown:
			case SWT.MouseDown:
			case SWT.MouseMove:
			case SWT.MouseWheel:
				toolTipHide(CURRENT_TOOLTIP, event);
				break;
			case SWT.MouseHover:
				toolTipCreate(event);
				break;
			case SWT.MouseExit:
				/*
				 * Check if the mouse exit happened because we move over the
				 * tooltip
				 */
				if (CURRENT_TOOLTIP != null && !CURRENT_TOOLTIP.isDisposed()) {
					if (CURRENT_TOOLTIP.getBounds().contains(
							control.toDisplay(event.x, event.y))) {
						break;
					}
				}

				toolTipHide(CURRENT_TOOLTIP, event);
				break;
			}
		}
	}

	private class TooltipHideListener implements Listener {
		public void handleEvent(Event event) {
			if (event.widget instanceof Control) {

				Control c = (Control) event.widget;
				Shell shell = c.getShell();

				switch (event.type) {
				case SWT.MouseDown:
					if (isHideOnMouseDown()) {
						toolTipHide(shell, event);
					}
					break;
				case SWT.MouseExit:
					/*
					 * Give some insets to ensure we get exit informations from
					 * a wider area ;-)
					 */
					Rectangle rect = shell.getBounds();
					rect.x += 5;
					rect.y += 5;
					rect.width -= 10;
					rect.height -= 10;

					if (!rect.contains(c.getDisplay().getCursorLocation())) {
						toolTipHide(shell, event);
					}

					break;
				}
			}
		}
	}
}
