/*******************************************************************************
 * Copyright (c) 2000, 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.jface.action;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;

/**
 * The standard abstract implementation of an action.
 * <p>
 * Subclasses must implement the <code>IAction.run</code> method to carry out
 * the action's semantics.
 * </p>
 */
public abstract class Action extends AbstractAction implements IAction {

	private static final IMenuCreator VAL_DROP_DOWN_MENU = new IMenuCreator() {
		public void dispose() {
			// do nothing
		}

		public Menu getMenu(Control parent) {
			// do nothing
			return null;
		}

		public Menu getMenu(Menu parent) {
			// do nothing
			return null;
		}
	};

	/*
	 * The list of default values the action can have. These values will
	 * determine the style of the action.
	 */
	private static final String VAL_PUSH_BTN = "PUSH_BTN"; //$NON-NLS-1$

	private static final Integer VAL_RADIO_BTN_OFF = new Integer(0);

	private static final Integer VAL_RADIO_BTN_ON = new Integer(1);

	private static final Boolean VAL_TOGGLE_BTN_OFF = Boolean.FALSE;

	private static final Boolean VAL_TOGGLE_BTN_ON = Boolean.TRUE;

	/**
	 * Converts an accelerator key code to a string representation.
	 * 
	 * @param keyCode
	 *            the key code to be translated
	 * @return a string representation of the key code
	 */
	public static String convertAccelerator(int keyCode) {
		return LegacyActionTools.convertAccelerator(keyCode);
	}

	/**
	 * Parses the given accelerator text, and converts it to an accelerator key
	 * code.
	 * 
	 * @param acceleratorText
	 *            the accelerator text
	 * @return the SWT key code, or 0 if there is no accelerator
	 */
	public static int convertAccelerator(String acceleratorText) {
		return LegacyActionTools.convertAccelerator(acceleratorText);
	}

	/**
	 * Maps a standard keyboard key name to an SWT key code. Key names are
	 * converted to upper case before comparison. If the key name is a single
	 * letter, for example "S", its character code is returned.
	 * <p>
	 * The following key names are known (case is ignored):
	 * <ul>
	 * <li><code>"BACKSPACE"</code></li>
	 * <li><code>"TAB"</code></li>
	 * <li><code>"RETURN"</code></li>
	 * <li><code>"ENTER"</code></li>
	 * <li><code>"ESC"</code></li>
	 * <li><code>"ESCAPE"</code></li>
	 * <li><code>"DELETE"</code></li>
	 * <li><code>"SPACE"</code></li>
	 * <li><code>"ARROW_UP"</code>, <code>"ARROW_DOWN"</code>,
	 * <code>"ARROW_LEFT"</code>, and <code>"ARROW_RIGHT"</code></li>
	 * <li><code>"PAGE_UP"</code> and <code>"PAGE_DOWN"</code></li>
	 * <li><code>"HOME"</code></li>
	 * <li><code>"END"</code></li>
	 * <li><code>"INSERT"</code></li>
	 * <li><code>"F1"</code>, <code>"F2"</code> through <code>"F12"</code></li>
	 * </ul>
	 * </p>
	 * 
	 * @param token
	 *            the key name
	 * @return the SWT key code, <code>-1</code> if no match was found
	 * @see SWT
	 */
	public static int findKeyCode(String token) {
		return LegacyActionTools.findKeyCode(token);
	}

	/**
	 * Maps an SWT key code to a standard keyboard key name. The key code is
	 * stripped of modifiers (SWT.CTRL, SWT.ALT, SWT.SHIFT, and SWT.COMMAND). If
	 * the key code is not an SWT code (for example if it a key code for the key
	 * 'S'), a string containing a character representation of the key code is
	 * returned.
	 * 
	 * @param keyCode
	 *            the key code to be translated
	 * @return the string representation of the key code
	 * @see SWT
	 * @since 2.0
	 */
	public static String findKeyString(int keyCode) {
		return LegacyActionTools.findKeyString(keyCode);
	}

	/**
	 * Maps standard keyboard modifier key names to the corresponding SWT
	 * modifier bit. The following modifier key names are recognized (case is
	 * ignored): <code>"CTRL"</code>, <code>"SHIFT"</code>,
	 * <code>"ALT"</code>, and <code>"COMMAND"</code>. The given modifier
	 * key name is converted to upper case before comparison.
	 * 
	 * @param token
	 *            the modifier key name
	 * @return the SWT modifier bit, or <code>0</code> if no match was found
	 * @see SWT
	 */
	public static int findModifier(String token) {
		return LegacyActionTools.findModifier(token);
	}

	/**
	 * Returns a string representation of an SWT modifier bit (SWT.CTRL,
	 * SWT.ALT, SWT.SHIFT, and SWT.COMMAND). Returns <code>null</code> if the
	 * key code is not an SWT modifier bit.
	 * 
	 * @param keyCode
	 *            the SWT modifier bit to be translated
	 * @return the string representation of the SWT modifier bit, or
	 *         <code>null</code> if the key code was not an SWT modifier bit
	 * @see SWT
	 * @since 2.0
	 */
	public static String findModifierString(int keyCode) {
		return LegacyActionTools.findModifierString(keyCode);
	}

	/**
	 * Convenience method for removing any optional accelerator text from the
	 * given string. The accelerator text appears at the end of the text, and is
	 * separated from the main part by a single tab character <code>'\t'</code>.
	 * 
	 * @param text
	 *            the text
	 * @return the text sans accelerator
	 */
	public static String removeAcceleratorText(String text) {
		return LegacyActionTools.removeAcceleratorText(text);
	}

	/**
	 * Convenience method for removing any mnemonics from the given string. For
	 * example, <code>removeMnemonics("&Open")</code> will return
	 * <code>"Open"</code>.
	 * 
	 * @param text
	 *            the text
	 * @return the text sans mnemonics
	 * 
	 * @since 3.0
	 */
	public static String removeMnemonics(String text) {
		return LegacyActionTools.removeMnemonics(text);
	}

	/**
	 * This action's accelerator; <code>0</code> means none.
	 */
	private int accelerator = 0;

	/**
	 * This action's action definition id, or <code>null</code> if none.
	 */
	private String actionDefinitionId;

	/**
	 * This action's description, or <code>null</code> if none.
	 */
	private String description;

	/**
	 * This action's disabled image, or <code>null</code> if none.
	 */
	private ImageDescriptor disabledImage;

	/**
	 * Indicates this action is enabled.
	 */
	private boolean enabled = true;

	/**
	 * An action's help listener, or <code>null</code> if none.
	 */
	private HelpListener helpListener;

	/**
	 * This action's hover image, or <code>null</code> if none.
	 */
	private ImageDescriptor hoverImage;

	/**
	 * This action's id, or <code>null</code> if none.
	 */
	private String id;

	/**
	 * This action's image, or <code>null</code> if none.
	 */
	private ImageDescriptor image;

	/**
	 * This action's text, or <code>null</code> if none.
	 */
	private String text;

	/**
	 * This action's tool tip text, or <code>null</code> if none.
	 */
	private String toolTipText;

	/**
	 * Holds the action's menu creator (an IMenuCreator) or checked state (a
	 * Boolean for toggle button, or an Integer for radio button), or
	 * <code>null</code> if neither have been set.
	 * <p>
	 * The value of this field affects the value of <code>getStyle()</code>.
	 * </p>
	 */
	private Object value = null;

	/**
	 * Creates a new action with no text and no image.
	 * <p>
	 * Configure the action later using the set methods.
	 * </p>
	 */
	protected Action() {
		// do nothing
	}

	/**
	 * Creates a new action with the given text and no image. Calls the zero-arg
	 * constructor, then <code>setText</code>.
	 * 
	 * @param text
	 *            the string used as the text for the action, or
	 *            <code>null</code> if there is no text
	 * @see #setText
	 */
	protected Action(String text) {
		this();
		setText(text);
	}

	/**
	 * Creates a new action with the given text and image. Calls the zero-arg
	 * constructor, then <code>setText</code> and
	 * <code>setImageDescriptor</code>.
	 * 
	 * @param text
	 *            the action's text, or <code>null</code> if there is no text
	 * @param image
	 *            the action's image, or <code>null</code> if there is no
	 *            image
	 * @see #setText
	 * @see #setImageDescriptor
	 */
	protected Action(String text, ImageDescriptor image) {
		this(text);
		setImageDescriptor(image);
	}

	/**
	 * Creates a new action with the given text and style.
	 * 
	 * @param text
	 *            the action's text, or <code>null</code> if there is no text
	 * @param style
	 *            one of <code>AS_PUSH_BUTTON</code>,
	 *            <code>AS_CHECK_BOX</code>, <code>AS_DROP_DOWN_MENU</code>,
	 *            <code>AS_RADIO_BUTTON</code>, and
	 *            <code>AS_UNSPECIFIED</code>.
	 */
	protected Action(String text, int style) {
		this(text);
		switch (style) {
		case AS_PUSH_BUTTON:
			value = VAL_PUSH_BTN;
			break;
		case AS_CHECK_BOX:
			value = VAL_TOGGLE_BTN_OFF;
			break;
		case AS_DROP_DOWN_MENU:
			value = VAL_DROP_DOWN_MENU;
			break;
		case AS_RADIO_BUTTON:
			value = VAL_RADIO_BTN_OFF;
			break;
		}
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public int getAccelerator() {
		return accelerator;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 * 
	 */
	public String getActionDefinitionId() {
		return actionDefinitionId;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public String getDescription() {
		if (description != null)
			return description;
		return getToolTipText();
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public ImageDescriptor getDisabledImageDescriptor() {
		return disabledImage;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public HelpListener getHelpListener() {
		return helpListener;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public ImageDescriptor getHoverImageDescriptor() {
		return hoverImage;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public String getId() {
		return id;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public ImageDescriptor getImageDescriptor() {
		return image;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public IMenuCreator getMenuCreator() {
		// The default drop down menu value is only used
		// to mark this action requested style. So do not
		// return it. For backward compatibility reasons.
		if (value == VAL_DROP_DOWN_MENU)
			return null;
		if (value instanceof IMenuCreator)
			return (IMenuCreator) value;
		return null;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public int getStyle() {
		// Infer the style from the value field.
		if (value == VAL_PUSH_BTN || value == null)
			return AS_PUSH_BUTTON;
		if (value == VAL_TOGGLE_BTN_ON || value == VAL_TOGGLE_BTN_OFF)
			return AS_CHECK_BOX;
		if (value == VAL_RADIO_BTN_ON || value == VAL_RADIO_BTN_OFF)
			return AS_RADIO_BUTTON;
		if (value instanceof IMenuCreator)
			return AS_DROP_DOWN_MENU;

		// We should never get to this line...
		return AS_PUSH_BUTTON;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public String getText() {
		return text;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public String getToolTipText() {
		return toolTipText;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public boolean isChecked() {
		return value == VAL_TOGGLE_BTN_ON || value == VAL_RADIO_BTN_ON;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public boolean isEnabled() {
		return enabled;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public boolean isHandled() {
		return true;
	}

	/**
	 * Reports the outcome of the running of this action via the
	 * {@link IAction#RESULT} property.
	 * 
	 * @param success
	 *            <code>true</code> if the action succeeded and
	 *            <code>false</code> if the action failed or was not completed
	 * @see IAction#RESULT
	 * @since 3.0
	 */
	public final void notifyResult(boolean success) {
		// avoid Boolean.valueOf(boolean) to allow compilation against JCL
		// Foundation (bug 80059)
		firePropertyChange(RESULT, null, success ? Boolean.TRUE : Boolean.FALSE);
	}

	/**
	 * The default implementation of this <code>IAction</code> method does
	 * nothing. Subclasses should override this method if they do not need
	 * information from the triggering event, or override
	 * <code>runWithEvent(Event)</code> if they do.
	 */
	public void run() {
		// do nothing
	}

	/**
	 * The default implementation of this <code>IAction</code> method ignores
	 * the event argument, and simply calls <code>run()</code>. Subclasses
	 * should override this method if they need information from the triggering
	 * event, or override <code>run()</code> if not.
	 * 
	 * @param event
	 *            the SWT event which triggered this action being run
	 * @since 2.0
	 */
	public void runWithEvent(Event event) {
		run();
	}

	/*
	 * @see IAction#setAccelerator(int)
	 */
	public void setAccelerator(int keycode) {
		this.accelerator = keycode;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setActionDefinitionId(String id) {
		actionDefinitionId = id;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setChecked(boolean checked) {
		Object newValue = null;

		// For backward compatibility, if the style is not
		// set yet, then convert it to a toggle button.
		if (value == null || value == VAL_TOGGLE_BTN_ON
				|| value == VAL_TOGGLE_BTN_OFF) {
			newValue = checked ? VAL_TOGGLE_BTN_ON : VAL_TOGGLE_BTN_OFF;
		} else if (value == VAL_RADIO_BTN_ON || value == VAL_RADIO_BTN_OFF) {
			newValue = checked ? VAL_RADIO_BTN_ON : VAL_RADIO_BTN_OFF;
		} else {
			// Some other style already, so do nothing.
			return;
		}

		if (newValue != value) {
			value = newValue;
			if (checked)
				firePropertyChange(CHECKED, Boolean.FALSE, Boolean.TRUE);
			else
				firePropertyChange(CHECKED, Boolean.TRUE, Boolean.FALSE);
		}
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setDescription(String text) {

		if ((description == null && text != null)
				|| (description != null && text == null)
				|| (description != null && text != null && !text
						.equals(description))) {
			String oldDescription = description;
			description = text;
			firePropertyChange(DESCRIPTION, oldDescription, description);
		}
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setDisabledImageDescriptor(ImageDescriptor newImage) {
		if (disabledImage != newImage) {
			ImageDescriptor oldImage = disabledImage;
			disabledImage = newImage;
			firePropertyChange(IMAGE, oldImage, newImage);
		}
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setEnabled(boolean enabled) {
		if (enabled != this.enabled) {
			Boolean oldVal = this.enabled ? Boolean.TRUE : Boolean.FALSE;
			Boolean newVal = enabled ? Boolean.TRUE : Boolean.FALSE;
			this.enabled = enabled;
			firePropertyChange(ENABLED, oldVal, newVal);
		}
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setHelpListener(HelpListener listener) {
		helpListener = listener;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setHoverImageDescriptor(ImageDescriptor newImage) {
		if (hoverImage != newImage) {
			ImageDescriptor oldImage = hoverImage;
			hoverImage = newImage;
			firePropertyChange(IMAGE, oldImage, newImage);
		}
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setId(String id) {
		this.id = id;
	}

	/*
	 * (non-Javadoc) Method declared on IAction.
	 */
	public void setImageDescriptor(ImageDescriptor newImage) {
		if (image != newImage) {
			ImageDescriptor oldImage = image;
			image = newImage;
			firePropertyChange(IMAGE, oldImage, newImage);
		}
	}

	/**
	 * Sets the menu creator for this action.
	 * <p>
	 * Note that if this method is called, it overrides the check status.
	 * </p>
	 * 
	 * @param creator
	 *            the menu creator, or <code>null</code> if none
	 */
	public void setMenuCreator(IMenuCreator creator) {
		// For backward compatibility, if the style is not
		// set yet, then convert it to a drop down menu.
		if (value == null) {
			value = creator;
			return;
		}

		if (value instanceof IMenuCreator)
			value = creator == null ? VAL_DROP_DOWN_MENU : creator;
	}

	/**
	 * Sets the text for this action.
	 * <p>
	 * Fires a property change event for the <code>TEXT</code> property if the
	 * text actually changes as a consequence.
	 * </p>
	 * <p>
	 * The accelerator is identified by the last index of a tab character. If
	 * there are no tab characters, then it is identified by the last index of a
	 * '@' character. If neither, then there is no accelerator text. Note that
	 * if you want to insert a '@' character into the text (but no accelerator,
	 * you can simply insert a '@' or a tab at the end of the text.
	 * </p>
	 * 
	 * @param text
	 *            the text, or <code>null</code> if none
	 */
	public void setText(String text) {
		String oldText = this.text;
		int oldAccel = this.accelerator;
		this.text = text;
		if (text != null) {
			String acceleratorText = LegacyActionTools
					.extractAcceleratorText(text);
			if (acceleratorText != null) {
				int newAccelerator = LegacyActionTools
						.convertLocalizedAccelerator(acceleratorText);
				// Be sure to not wipe out the accelerator if nothing found
				if (newAccelerator > 0) {
					setAccelerator(newAccelerator);
				}
			}
		}
		if (!(this.accelerator == oldAccel && (oldText == null ? this.text == null
				: oldText.equals(this.text)))) {
			firePropertyChange(TEXT, oldText, this.text);
		}
	}

	/**
	 * Sets the tool tip text for this action.
	 * <p>
	 * Fires a property change event for the <code>TOOL_TIP_TEXT</code>
	 * property if the tool tip text actually changes as a consequence.
	 * </p>
	 * 
	 * @param toolTipText
	 *            the tool tip text, or <code>null</code> if none
	 */
	public void setToolTipText(String toolTipText) {
		String oldToolTipText = this.toolTipText;
		if (!(oldToolTipText == null ? toolTipText == null : oldToolTipText
				.equals(toolTipText))) {
			this.toolTipText = toolTipText;
			firePropertyChange(TOOL_TIP_TEXT, oldToolTipText, toolTipText);
		}
	}

}
