/*******************************************************************************
 * Copyright (c) 2008, 2016 Ketan Padegaonkar 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:
 *     Ketan Padegaonkar - initial API and implementation
 *     Lorenzo Bettini - (Bug 426869) mark new methods with since annotation
 *     Patrick Tasse - Improve SWTBot menu API and implementation (Bug 479091)
 *     Aparna Argade(Cadence Design Systems, Inc.) - Bug 489179
 *******************************************************************************/
package org.eclipse.swtbot.swt.finder.widgets;

import static org.eclipse.swtbot.swt.finder.waits.Conditions.widgetIsEnabled;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.util.Geometry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
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.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
import org.eclipse.swtbot.swt.finder.finders.ContextMenuHelper;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.keyboard.Keyboard;
import org.eclipse.swtbot.swt.finder.keyboard.KeyboardFactory;
import org.eclipse.swtbot.swt.finder.keyboard.Keystrokes;
import org.eclipse.swtbot.swt.finder.matchers.WithId;
import org.eclipse.swtbot.swt.finder.results.ArrayResult;
import org.eclipse.swtbot.swt.finder.results.BoolResult;
import org.eclipse.swtbot.swt.finder.results.IntResult;
import org.eclipse.swtbot.swt.finder.results.ListResult;
import org.eclipse.swtbot.swt.finder.results.Result;
import org.eclipse.swtbot.swt.finder.results.StringResult;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.swtbot.swt.finder.results.WidgetResult;
import org.eclipse.swtbot.swt.finder.utils.MessageFormat;
import org.eclipse.swtbot.swt.finder.utils.SWTBotEvents;
import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
import org.eclipse.swtbot.swt.finder.utils.Traverse;
import org.eclipse.swtbot.swt.finder.utils.WidgetTextDescription;
import org.eclipse.swtbot.swt.finder.utils.internal.Assert;
import org.eclipse.swtbot.swt.finder.waits.Conditions;
import org.eclipse.swtbot.swt.finder.waits.WaitForObjectCondition;
import org.hamcrest.SelfDescribing;
import org.hamcrest.StringDescription;

/**
 * Helper to find SWT {@link Widget}s and perform operations on them.
 *
 * @author Ketan Padegaonkar &lt;KetanPadegaonkar [at] gmail [dot] com&gt;
 * @author Joshua Gosse &lt;jlgosse [at] ca [dot] ibm [dot] com&gt;
 * @author Lorenzo Bettini - (Bug 426869) mark new methods with since annotation
 * @version $Id$
 */
public abstract class AbstractSWTBot<T extends Widget> {

	/** The logger. */
	protected final Logger			log;
	/** With great power comes great responsibility, use carefully. */
	public final T					widget;
	/** With great power comes great responsibility, use carefully. */
	public final Display			display;
	/** The description of the widget. */
	protected final SelfDescribing	description;
	/** The keyboard to use to type on the widget. */
	private Keyboard				keyboard;

	/**
	 * Constructs a new instance with the given widget.
	 *
	 * @param w the widget.
	 * @throws WidgetNotFoundException if the widget is <code>null</code> or widget has been disposed.
	 */
	public AbstractSWTBot(T w) throws WidgetNotFoundException {
		this(w, new WidgetTextDescription(w));
	}

	/**
	 * Constructs a new instance with the given widget.
	 *
	 * @param w the widget.
	 * @param description the description of the widget, this will be reported by {@link #toString()}
	 * @throws WidgetNotFoundException if the widget is <code>null</code> or widget has been disposed.
	 */
	public AbstractSWTBot(T w, SelfDescribing description) throws WidgetNotFoundException {
		if (w == null)
			throw new WidgetNotFoundException("The widget was null."); //$NON-NLS-1$

		this.widget = w;
		if (description == null)
			this.description = new WidgetTextDescription(w);
		else
			this.description = description;

		if (w.isDisposed())
			throw new WidgetNotFoundException("The widget {" + description + "} was disposed." + SWTUtils.toString(w)); //$NON-NLS-1$ //$NON-NLS-2$

		display = w.getDisplay();
		log = Logger.getLogger(getClass());
	}

	/**
	 * Sends a non-blocking notification of the specified type to the widget.
	 *
	 * @param eventType the event type.
	 * @see Widget#notifyListeners(int, Event)
	 */
	protected void notify(final int eventType) {
		notify(eventType, createEvent());
	}

	/**
	 * Sends a non-blocking notification of the specified type to the {@link #widget}.
	 *
	 * @param eventType the type of event.
	 * @param createEvent the event to be sent to the {@link #widget}.
	 */
	protected void notify(final int eventType, final Event createEvent) {
		notify(eventType, createEvent, widget);
	}

	/**
	 * Sends a non-blocking notification of the specified type to the widget.
	 *
	 * @param eventType the type of event.
	 * @param createEvent the event to be sent to the {@link #widget}.
	 * @param widget the widget to send the event to.
	 */
	protected void notify(final int eventType, final Event createEvent, final Widget widget) {
		createEvent.type = eventType;
		final Object[] result = syncExec(new ArrayResult<Object>() {
			public Object[] run() {
				return new Object[] { SWTBotEvents.toString(createEvent), AbstractSWTBot.this.toString() };
			}
		});

		log.trace(MessageFormat.format("Enquing event {0} on {1}", result)); //$NON-NLS-1$
		asyncExec(new VoidResult() {
			public void run() {
				if ((widget == null) || widget.isDisposed()) {
					log.trace(MessageFormat.format("Not notifying {0} is null or has been disposed", AbstractSWTBot.this)); //$NON-NLS-1$
					return;
				}
				if (!isEnabledInternal()) {
					log.warn(MessageFormat.format("Widget is not enabled: {0}", AbstractSWTBot.this)); //$NON-NLS-1$
					return;
				}
				log.trace(MessageFormat.format("Sending event {0} to {1}", result)); //$NON-NLS-1$
				widget.notifyListeners(eventType, createEvent);
				log.debug(MessageFormat.format("Sent event {0} to {1}", result)); //$NON-NLS-1$
			}
		});

		UIThreadRunnable.syncExec(new VoidResult() {
			public void run() {
				// do nothing, just wait for sync.
			}
		});

		long playbackDelay = SWTBotPreferences.PLAYBACK_DELAY;
		if (playbackDelay > 0)
			sleep(playbackDelay);
	}

	/**
	 * Sleeps for millis milliseconds. Delegate to {@link SWTUtils#sleep(long)}
	 *
	 * @param millis the time in milli seconds
	 */
	protected static void sleep(long millis) {
		SWTUtils.sleep(millis);
	}

	/**
	 * Creates an event.
	 *
	 * @return an event that encapsulates {@link #widget} and {@link #display}. Subclasses may override to set other
	 *         event properties.
	 */
	protected Event createEvent() {
		Event event = new Event();
		event.time = (int) System.currentTimeMillis();
		event.widget = widget;
		event.display = display;
		return event;
	}

	/**
	 * Create a mouse event
	 *
	 * @param x the x co-ordinate of the mouse event.
	 * @param y the y co-ordinate of the mouse event.
	 * @param button the mouse button that was clicked.
	 * @param stateMask the state of the keyboard modifier keys.
	 * @param count the number of times the mouse was clicked.
	 * @return an event that encapsulates {@link #widget} and {@link #display}
	 * @since 1.2
	 */
	protected Event createMouseEvent(int x, int y, int button, int stateMask, int count) {
		Event event = new Event();
		event.time = (int) System.currentTimeMillis();
		event.widget = widget;
		event.display = display;
		event.x = x;
		event.y = y;
		event.button = button;
		event.stateMask = stateMask;
		event.count = count;
		return event;
	}

	/**
	 * Create a selection event with a particular state mask
	 *
	 * @param stateMask the state of the keyboard modifier keys.
	 */
	protected Event createSelectionEvent(int stateMask) {
		Event event = createEvent();
		event.stateMask = stateMask;
		return event;
	}

	/**
	 * Click on the table at given coordinates
	 *
	 * @param x the x co-ordinate of the click
	 * @param y the y co-ordinate of the click
	 * @since 2.0
	 */
	protected void clickXY(int x, int y) {
		log.debug(MessageFormat.format("Clicking on {0}", this)); //$NON-NLS-1$
		notify(SWT.MouseEnter);
		notify(SWT.MouseMove);
		notify(SWT.Activate);
		notify(SWT.FocusIn);
		notify(SWT.MouseDown, createMouseEvent(x, y, 1, SWT.NONE, 1));
		notify(SWT.MouseUp, createMouseEvent(x, y, 1, SWT.BUTTON1, 1));
		notify(SWT.Selection, createSelectionEvent(SWT.BUTTON1));
		notify(SWT.MouseHover);
		notify(SWT.MouseMove);
		notify(SWT.MouseExit);
		notify(SWT.Deactivate);
		notify(SWT.FocusOut);
		log.debug(MessageFormat.format("Clicked on {0}", this)); //$NON-NLS-1$
	}

	/**
	 * Right click on the widget at given coordinates
	 *
	 * @param x the x co-ordinate of the click
	 * @param y the y co-ordinate of the click
	 * @since 2.0
	 */
	private void rightClickXY(int x, int y) {
		log.debug(MessageFormat.format("Right clicking on {0}", this)); //$NON-NLS-1$
		notify(SWT.MouseEnter);
		notify(SWT.MouseMove);
		notify(SWT.Activate);
		notify(SWT.FocusIn);
		notify(SWT.MouseDown, createMouseEvent(x, y, 3, SWT.NONE, 1));
		notify(SWT.MouseUp, createMouseEvent(x, y, 3, SWT.BUTTON3, 1));
		notify(SWT.Selection, createSelectionEvent(SWT.BUTTON3));
		notify(SWT.MouseHover);
		notify(SWT.MouseMove);
		notify(SWT.MouseExit);
		notify(SWT.Deactivate);
		notify(SWT.FocusOut);
		log.debug(MessageFormat.format("Right clicked on {0}", this)); //$NON-NLS-1$
	}

	/**
	 * Double-click on the table at given coordinates
	 *
	 * @param x the x co-ordinate of the click
	 * @param y the y co-ordinate of the click
	 * @since 2.0
	 */
	protected void doubleClickXY(int x, int y) {
		log.debug(MessageFormat.format("Double-clicking on {0}", widget)); //$NON-NLS-1$
		notify(SWT.MouseEnter);
		notify(SWT.MouseMove);
		notify(SWT.Activate);
		notify(SWT.FocusIn);
		notify(SWT.MouseDown, createMouseEvent(x, y, 1, SWT.NONE, 1));
		notify(SWT.MouseUp, createMouseEvent(x, y, 1, SWT.BUTTON1, 1));
		notify(SWT.Selection, createSelectionEvent(SWT.BUTTON1));
		notify(SWT.MouseDoubleClick, createMouseEvent(x, y, 1, SWT.BUTTON1, 2));
		notify(SWT.MouseHover);
		notify(SWT.MouseMove);
		notify(SWT.MouseExit);
		notify(SWT.Deactivate);
		notify(SWT.FocusOut);
		log.debug(MessageFormat.format("Double-clicked on {0}", widget)); //$NON-NLS-1$
	}

	@Override
	public String toString() {
		return StringDescription.toString(description);
	}

	// /**
	// * Finds a menu matching the current {@link Matcher}.
	// *
	// * @param matcher the matcher used to find menus.
	// * @return all menus that match the matcher.
	// */
	// protected List findMenus(Matcher<?> matcher) {
	// return finder.findMenus(matcher);
	// }

	// /**
	// * Finds the menu on the main menu bar matching the given information.
	// *
	// * @param menuName the name of the menu.
	// * @param matcher the matcher used to find the menu.
	// * @return the first menuItem that matches the matcher
	// * @throws WidgetNotFoundException if the widget is not found.
	// */
	// protected Widget findMenu(Matcher<?> matcher, String menuName) throws WidgetNotFoundException {
	// return findMenu(getMenuMatcher(menuName), 0);
	// }

	// /**
	// * Gets the menu matcher for the given name.
	// *
	// * @param menuName the name of the menuitem that the matcher must match.
	// * @return {@link WidgetMatcherFactory#menuMatcher(String)}
	// */
	// protected Matcher getMenuMatcher(String menuName) {
	// return WidgetMatcherFactory.menuMatcher(menuName);
	// }

	// /**
	// * Finds the menu on the main menu bar matching the given information.
	// *
	// * @param matcher the matcher used to find the menu.
	// * @param index the index in the list of the menu items that match the matcher.
	// * @return the index(th) menuItem that matches the matcher
	// * @throws WidgetNotFoundException if the widget is not found.
	// */
	// protected Widget findMenu(Matcher<?> matcher, int index) throws WidgetNotFoundException {
	// List findMenus = findMenus(matcher);
	// if (!findMenus.isEmpty())
	// return (MenuItem) findMenus.get(index);
	// throw new WidgetNotFoundException("Could not find menu using matcher " + matcher);
	// }

	/**
	 * Gets the text of this object's widget.
	 *
	 * @return the text on the widget.
	 */
	public String getText() {
		return SWTUtils.getText(widget);
	}

	/**
	 * Gets the value of {@link Widget#getData(String))} for the key {@link SWTBotPreferences#DEFAULT_KEY} of this
	 * object's widget.
	 *
	 * @return the id that SWTBot may use to search this widget.
	 * @see WithId
	 */
	public String getId() {
		return syncExec(new StringResult() {
			public String run() {
				return (String) widget.getData(SWTBotPreferences.DEFAULT_KEY);
			}
		});
	}

	/**
	 * Gets the tooltip of this object's widget.
	 *
	 * @return the tooltip on the widget.
	 * @since 1.0
	 */
	public String getToolTipText() {
		return syncExec(new StringResult() {
			public String run() {
				return SWTUtils.getToolTipText(widget);
			}
		});
	}

	/**
	 * Check if this widget has a style attribute.
	 *
	 * @param w the widget.
	 * @param style the style bits, one of the constants in {@link SWT}.
	 * @return <code>true</code> if style is set on the widget.
	 */
	protected boolean hasStyle(Widget w, int style) {
		return SWTUtils.hasStyle(w, style);
	}

	/**
	 * Gets the context menu of this widget.
	 * <p>
	 * The context menu is invoked at the center of this widget.
	 *
	 * @return the context menu.
	 * @throws WidgetNotFoundException if the widget is not found.
	 * @since 2.4
	 */
	public SWTBotRootMenu contextMenu() throws WidgetNotFoundException {
		if (widget instanceof Control) {
			return contextMenu((Control) widget);
		}
		throw new WidgetNotFoundException("Could not find context menu for widget: " + widget); //$NON-NLS-1$
	}

	/**
	 * Gets the context menu of the given control.
	 * <p>
	 * The context menu is invoked at the center of this widget.
	 *
	 * @param control the control.
	 * @return the context menu.
	 * @throws WidgetNotFoundException if the widget is not found.
	 * @since 2.4
	 */
	protected SWTBotRootMenu contextMenu(final Control control) throws WidgetNotFoundException {
		ContextMenuHelper.notifyMenuDetect(control, widget);

		WaitForObjectCondition<Menu> waitForMenu = Conditions.waitForPopupMenu(control);
		new SWTBot().waitUntilWidgetAppears(waitForMenu);
		return new SWTBotRootMenu(waitForMenu.get(0));
	}

	/**
	 * Gets the context menu item matching the given text. It will attempt to
	 * find the menu item recursively in each of the sub-menus that are found.
	 * <p>
	 * This is equivalent to calling contextMenu().menu(text, true, 0);
	 *
	 * @param text the text on the context menu item.
	 * @return the context menu item that has the given text.
	 * @throws WidgetNotFoundException if the widget is not found.
	 */
	public SWTBotMenu contextMenu(final String text) throws WidgetNotFoundException {
		return contextMenu().menu(text, true, 0);
	}

	/**
	 * Gets the context menu item matching the given text on the given control.
	 * It will attempt to find the menu item recursively in each of the
	 * sub-menus that are found.
	 * <p>
	 * This is equivalent to calling contextMenu(control).menu(text, true, 0);
	 *
	 * @param control the control.
	 * @param text the text on the context menu item.
	 * @return the context menu item that has the given text.
	 * @throws WidgetNotFoundException if the widget is not found.
	 * @since 2.0
	 */
	protected SWTBotMenu contextMenu(final Control control, final String text) {
		return contextMenu(control).menu(text, true, 0);
	}

	/**
	 * Gets if the object's widget is enabled.
	 *
	 * @return <code>true</code> if the widget is enabled.
	 * @see Control#isEnabled()
	 */
	public boolean isEnabled() {
		if (widget instanceof Control)
			return syncExec(new BoolResult() {
				public Boolean run() {
					return isEnabledInternal();
				}
			});
		return false;
	}

	/**
	 * Gets if the widget is enabled.
	 * <p>
	 * This method is not thread safe, and must be called from the UI thread.
	 * </p>
	 *
	 * @return <code>true</code> if the widget is enabled.
	 * @since 1.0
	 */
	protected boolean isEnabledInternal() {
		try {
			return ((Boolean) SWTUtils.invokeMethod(widget, "isEnabled")).booleanValue(); //$NON-NLS-1$
		} catch (Exception e) {
			return true;
		}
	}

	/**
	 * Invokes {@link ArrayResult#run()} on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 * @return the array returned by toExecute.
	 */
	protected <E> E[] syncExec(ArrayResult<E> toExecute) {
		return UIThreadRunnable.syncExec(display, toExecute);
	}

	/**
	 * Invokes {@link VoidResult#run()} on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 */
	protected void syncExec(VoidResult toExecute) {
		UIThreadRunnable.syncExec(display, toExecute);
	}

	/**
	 * Invokes {@link ListResult#run()} on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 * @return the list returned by toExecute
	 */
	protected <E> List<E> syncExec(ListResult<E> toExecute) {
		return UIThreadRunnable.syncExec(display, toExecute);
	}

	/**
	 * Invokes {@link BoolResult#run()} synchronously on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 * @return the boolean returned by toExecute
	 */
	protected boolean syncExec(BoolResult toExecute) {
		return UIThreadRunnable.syncExec(display, toExecute);
	}

	/**
	 * Invokes {@link BoolResult#run()} synchronously on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 * @return the boolean returned by toExecute
	 */

	protected String syncExec(StringResult toExecute) {
		return UIThreadRunnable.syncExec(display, toExecute);
	}

	/**
	 * Invokes {@link Result#run()} synchronously on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 * @return the boolean returned by toExecute
	 */
	protected <E> E syncExec(Result<E> toExecute) {
		return UIThreadRunnable.syncExec(display, toExecute);
	}

	/**
	 * Invokes {@link WidgetResult#run()} synchronously on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 * @return the Widget returned by toExecute
	 */
	protected T syncExec(WidgetResult<T> toExecute) {
		return UIThreadRunnable.syncExec(display, toExecute);
	}

	/**
	 * Invokes {@link IntResult#run()} synchronously on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 * @return the integer returned by toExecute
	 */

	protected int syncExec(IntResult toExecute) {
		return UIThreadRunnable.syncExec(display, toExecute);
	}

	/**
	 * Invokes {@link BoolResult#run()} asynchronously on the UI thread.
	 *
	 * @param toExecute the object to be invoked in the UI thread.
	 */
	protected void asyncExec(VoidResult toExecute) {
		UIThreadRunnable.asyncExec(display, toExecute);
	}

	/**
	 * Gets the foreground color of the widget.
	 *
	 * @return the foreground color on the widget, or <code>null</code> if the widget is not an instance of
	 *         {@link Control}.
	 * @since 1.0
	 */
	public Color foregroundColor() {
		return syncExec(new Result<Color>() {
			public Color run() {
				if (widget instanceof Control)
					return ((Control) widget).getForeground();
				return null;
			}
		});
	}

	/**
	 * Gets the background color of the widget.
	 *
	 * @return the background color on the widget, or <code>null</code> if the widget is not an instance of
	 *         {@link Control}.
	 * @since 1.0
	 */
	public Color backgroundColor() {
		return syncExec(new Result<Color>() {
			public Color run() {
				if (widget instanceof Control)
					return ((Control) widget).getBackground();
				return null;
			}
		});
	}

	/**
	 * Check if the widget is enabled, throws if the widget is disabled.
	 *
	 * @since 1.3
	 */
	protected void assertEnabled() {
		Assert.isTrue(isEnabled(), MessageFormat.format("Widget {0} is not enabled.", this)); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Wait until the widget is enabled.
	 *
	 * @since 2.0
	 */
	protected void waitForEnabled() {
		new SWTBot().waitUntil(widgetIsEnabled(this));
	}

	/**
	 * Checks if the widget is visible.
	 *
	 * @return <code>true</code> if the widget is visible, <code>false</code> otherwise.
	 * @since 1.0
	 */
	public boolean isVisible() {
		return syncExec(new BoolResult() {
			public Boolean run() {
				if (widget instanceof Control)
					return ((Control) widget).isVisible();
				return true;
			}
		});
	}

	/**
	 * Sets the focus on this control.
	 *
	 * @since 1.2
	 */
	public void setFocus() {
		waitForEnabled();
		log.debug(MessageFormat.format("Attempting to set focus on {0}", this));
		syncExec(new VoidResult() {
			public void run() {
				if (widget instanceof Control) {
					Control control = (Control) widget;
					if (hasFocus(control))
						return;
					control.getShell().forceActive();
					control.getShell().forceFocus();
					control.forceFocus();
				}
			}

			private boolean hasFocus(Control control) {
				return control.isFocusControl();
			}
		});
	}

	/**
	 * @param traverse the kind of traversal to perform.
	 * @return <code>true</code> if the traversal succeeded.
	 * @see Control#traverse(int)
	 */
	public boolean traverse(final Traverse traverse) {
		waitForEnabled();
		setFocus();

		if (!(widget instanceof Control))
			throw new UnsupportedOperationException("Can only traverse widgets of type Control. You're traversing a widget of type: " //$NON-NLS-1$
					+ widget.getClass().getName());

		return syncExec(new BoolResult() {
			public Boolean run() {
				return ((Control) widget).traverse(traverse.type);
			}
		});
	}

	/**
	 * @return <code>true</code> if this widget has focus.
	 * @see Display#getFocusControl()
	 */
	public boolean isActive() {
		return syncExec(new BoolResult() {
			public Boolean run() {
				return display.getFocusControl() == widget;
			}
		});
	}

	/**
	 * Clicks on this widget.
	 *
	 * @return itself.
	 */
	protected AbstractSWTBot<T> click() {
		throw new UnsupportedOperationException("This operation is not supported by this widget.");
	}

	/**
	 * Empty method stub, since it should be overridden by subclass#rightClick
	 *
	 * @return itself.
	 */
	protected AbstractSWTBot<T> rightClick() {
		throw new UnsupportedOperationException("This operation is not supported by this widget.");
	}

	/**
	 * Perform a click action at the given coordinates
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 * @param post Whether or not {@link Display#post} should be used
	 * @return itself.
	 */
	protected AbstractSWTBot<T> click(final int x, final int y, final boolean post) {
		if (post) {
			asyncExec(new VoidResult() {
				public void run() {
					moveMouse(x, y);
					mouseDown(x, y, 1);
					mouseUp(x, y, 1);
				}
			});
			sleep(500);
		} else
			clickXY(x, y);
		return this;
	}

	/**
	 * Perform a right-click action at the given coordinates
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 * @param post Whether or not {@link Display#post} should be used
	 * @return itself.
	 */
	protected AbstractSWTBot<T> rightClick(final int x, final int y, final boolean post) {
		if (post) {
			syncExec(new VoidResult() {
				public void run() {
					moveMouse(x, y);
					mouseDown(x, y, 3);
					mouseUp(x, y, 3);
				}
			});
		} else
			rightClickXY(x, y);
		return this;
	}

	/**
	 * Post an SWT.MouseMove event
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 */
	void moveMouse(final int x, final int y) {
		asyncExec(new VoidResult() {
			public void run() {
				Event event = createMouseEvent(x, y, 0, 0, 0);
				event.type = SWT.MouseMove;
				display.post(event);
			}
		});
	}

	/**
	 * Post an SWT.MouseDown event
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 * @param button the mouse button to be pressed
	 */
	private void mouseDown(final int x, final int y, final int button) {
		asyncExec(new VoidResult() {
			public void run() {
				Event event = createMouseEvent(x, y, button, 0, 0);
				event.type = SWT.MouseDown;
				display.post(event);
			}
		});
	}

	/**
	 * Post an SWT.MouseUp event.
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 * @param button the mouse button to be pressed
	 */
	private void mouseUp(final int x, final int y, final int button) {
		asyncExec(new VoidResult() {
			public void run() {
				Event event = createMouseEvent(x, y, button, 0, 0);
				event.type = SWT.MouseUp;
				display.post(event);
			}
		});
	}

	/**
	 * @return the absolute location of the widget relative to the display.
	 */
	protected Rectangle absoluteLocation() {
		throw new UnsupportedOperationException("This operation is not supported by this widget.");
	}

	/**
	 * @return the keyboard to use to type on this widget.
	 */
	protected Keyboard keyboard() {
		if (keyboard == null)
			keyboard = KeyboardFactory.getDefaultKeyboard(widget, description);
		return keyboard;
	}

	/**
	 * Presses the shortcut specified by the given keys.
	 *
	 * @param modificationKeys the combination of {@link SWT#ALT} | {@link SWT#CTRL} | {@link SWT#SHIFT} |
	 *            {@link SWT#COMMAND}.
	 * @param c the character
	 * @return the same instance
	 * @see Keystrokes#toKeys(int, char)
	 */
	public AbstractSWTBot<T> pressShortcut(int modificationKeys, char c) {
		waitForEnabled();
		setFocus();
		keyboard().pressShortcut(modificationKeys, c);
		return this;
	}

	/**
	 * Presses the shortcut specified by the given keys.
	 *
	 * @param modificationKeys the combination of {@link SWT#ALT} | {@link SWT#CTRL} | {@link SWT#SHIFT} | {@link SWT#COMMAND}.
	 * @param keyCode the keyCode, these may be special keys like F1-F12, or navigation keys like HOME, PAGE_UP
	 * @param c the character
	 * @return the same instance
	 * @see Keystrokes#toKeys(int, char)
	 */
	public AbstractSWTBot<T> pressShortcut(int modificationKeys, int keyCode, char c) {
		waitForEnabled();
		setFocus();
		keyboard().pressShortcut(modificationKeys, keyCode, c);
		return this;
	}

	/**
	 * Presses the shortcut specified by the given keys.
	 *
	 * @param keys the keys to press
	 * @return the same instance
	 * @see Keyboard#pressShortcut(KeyStroke...)
	 * @see Keystrokes
	 */
	public AbstractSWTBot<T> pressShortcut(KeyStroke... keys) {
		waitForEnabled();
		setFocus();
		keyboard().pressShortcut(keys);
		return this;
	}
	
	/**
	 * @since 2.2
	 */
	public void dragAndDrop(final AbstractSWTBot<? extends Widget> target) {
		final Rectangle sourceRect = absoluteLocation();
		final Rectangle destRect = target.absoluteLocation();
		dragAndDropPointToPoint(Geometry.centerPoint(sourceRect), Geometry.centerPoint(destRect));
	}
	
	private void dragAndDropPointToPoint(final Point source, final Point dest) {
		try {
			final Robot robot = new Robot();
			syncExec(new VoidResult() {
				public void run() {
					robot.mouseMove(source.x, source.y);
					robot.mousePress(InputEvent.BUTTON1_MASK);
					robot.mouseMove((source.x + 10), source.y);
				}
			});

			waitForIdle(robot);

			syncExec(new VoidResult() {
				public void run() {
					robot.mouseMove((dest.x + 10), dest.y);
					robot.mouseMove(dest.x, dest.y);
				}
			});

			waitForIdle(robot);

			syncExec(new VoidResult() {
				public void run() {
					robot.mouseRelease(InputEvent.BUTTON1_MASK);
				}
			});
		waitForIdle(robot);
		} catch (final AWTException e) {
			 log.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}

	}

	private void waitForIdle(final Robot robot) {
		if (SWT.getPlatform().equals("gtk")) {
			robot.waitForIdle();
		}
	}
}

