/*******************************************************************************
 * Copyright (c) 2000, 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.widgets;

import intrinsic.Function;
import intrinsic.mx.collections.ArrayCollection;
import intrinsic.mx.controls.MenuBar;
import intrinsic.mx.core.Container;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.flex.SWTMenu;
import org.eclipse.swt.internal.flex.SWTMenuDataDescriptor;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.events.MenuListener;

public class Menu extends Widget {
	Decorations parent;
	MenuItem cascade;
	int x, y;
	boolean hasLocation;
	public ArrayCollection items;//TODO referenced by SWTMenuDataDescriptor

public Menu (Control parent) {
	this (checkNull (parent).menuShell (), SWT.POP_UP);
}

public Menu (Decorations parent, int style) {
	super (parent, checkStyle (style));
	this.parent = parent;
	createWidget ();
}

public Menu (Menu parentMenu) {
	this (checkNull (parentMenu).parent, SWT.DROP_DOWN);
}

public Menu (MenuItem parentItem) {
	this (checkNull (parentItem).parent);
}

public void addHelpListener (HelpListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Help, typedListener);
}

public void addMenuListener (MenuListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Hide,typedListener);
	addListener (SWT.Show,typedListener);
}

static Control checkNull (Control control) {
	if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	return control;
}

static Menu checkNull (Menu menu) {
	if (menu == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	return menu;
}

static MenuItem checkNull (MenuItem item) {
	if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	return item;
}

static int checkStyle (int style) {
	return checkBits (style, SWT.POP_UP, SWT.BAR, SWT.DROP_DOWN, 0, 0, 0);
}

void createHandle () {
	if ((style & SWT.BAR) != 0) {
		MenuBar menu = new MenuBar();
		menu.dataProvider = items = new ArrayCollection();
		menu.dataDescriptor = new SWTMenuDataDescriptor();
		menu.labelFunction = getLabelFunction();
		menu.percentWidth = 100;
		object = menu;
	} else {
		items = new ArrayCollection();
		intrinsic.mx.controls.Menu menu = new SWTMenu();
		intrinsic.mx.controls.Menu.popUpMenu(menu, parent.object, items); 
		menu.dataDescriptor = new SWTMenuDataDescriptor();
		menu.labelFunction = getLabelFunction();
		menu.iconFunction = getIconFunction();
		object = menu;
	}
}

void createItem (MenuItem item, int index) {
	int itemCount = items.length;
	if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
	item.createWidget();
	items.addItemAt(item, index);
}

public MenuItem getDefaultItem () {
	checkWidget();
	return null;
}

public boolean getEnabled () {
	checkWidget();
	return object.enabled;
}

public MenuItem getItem (int index) {
	checkWidget ();
	int itemCount = items.length;
	if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
	return (MenuItem) items.getItemAt(index);
}

public int getItemCount () {
	checkWidget ();
	return items.length;
}

public MenuItem[] getItems () {
	checkWidget ();
	MenuItem [] result = new MenuItem [items.length];
	for (int i = 0; i < result.length; i++) {
		result[i] = (MenuItem)items.getItemAt(i);
	}
	return result;
}

public Decorations getParent () {
	checkWidget ();
	return parent;
}

public MenuItem getParentItem () {
	checkWidget ();
	return cascade;
}

public Menu getParentMenu () {
	checkWidget ();
	if (cascade != null) return cascade.parent;
	return null;
}

public Shell getShell () {
	checkWidget ();
	return parent.getShell ();
}

public boolean getVisible () {
	checkWidget();
	return object.visible;
}

public int indexOf (MenuItem item) {
	checkWidget ();
	return items.getItemIndex(item);
}

void invalidateItem (MenuItem item) {
	items.itemUpdated (item);
}

public boolean isEnabled () {
	checkWidget();
	Menu parentMenu = getParentMenu ();
	if (parentMenu == null) {
		return getEnabled () && parent.isEnabled ();
	}
	return getEnabled () && parentMenu.isEnabled ();
}

public boolean isVisible () {
	checkWidget();
	return getVisible ();
}

String labelFunction (MenuItem item)  {
	return item.getText ();
}

native Function getLabelFunction () /*{
	return labelFunction__Lorg_eclipse_swt_widgets_MenuItem_2;
}*/;

String iconFunction (Object object)  {
	//TODO - not called
	return null;
}

native Function getIconFunction () /*{
	return iconFunction__Ljava_lang_Object_2;
}*/;

public void removeHelpListener (HelpListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Help, listener);
}

public void removeMenuListener (MenuListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Hide, listener);
	eventTable.unhook (SWT.Show, listener);
}

public void setDefaultItem (MenuItem item) {
	checkWidget();
}

public void setEnabled (boolean enabled) {
	checkWidget ();
	object.enabled = enabled;
}

public void setLocation (int x, int y) {
	checkWidget ();
	if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
	this.x = x;
	this.y = y;
	hasLocation = true;
}

public void setLocation (Point location) {
	checkWidget ();
	if (location == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	setLocation (location.x, location.y);
}

public void setVisible (boolean visible) {
	checkWidget ();
	if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
	int nX = x, nY = y;
	if (!hasLocation) {
		Container root = display.root;
		nX = (int)root.mouseX;
		nY = (int)root.mouseY;
	}
	((SWTMenu)object).show(nX, nY);
}

void itemClickHandler(intrinsic.mx.events.MenuEvent event) {
	((MenuItem)event.item).sendEvent(SWT.Selection);
}

void menuShowHandler(intrinsic.mx.events.MenuEvent event) {
	if ((style & SWT.BAR) != 0) ((MenuItem)items.getItemAt(event.menuBar.selectedIndex)).menu.sendEvent(SWT.Show);
}

native Function itemClickHandlerFunction ()/*{
	return itemClickHandler__Lmx_events_MenuEvent_2;
}*/;

native Function menuShowHandlerFunction ()/*{
	return menuShowHandler__Lmx_events_MenuEvent_2;
}*/;

void hookEvents (){
	super.hookEvents();
	object.addEventListener(intrinsic.mx.events.MenuEvent.ITEM_CLICK, itemClickHandlerFunction ());
	object.addEventListener(intrinsic.mx.events.MenuEvent.MENU_SHOW, menuShowHandlerFunction ());	
}

}
