/*******************************************************************************
 * 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.ComboBox;
import intrinsic.mx.controls.TextInput;
import intrinsic.mx.controls.listClasses.ListBase;
import intrinsic.mx.events.FlexEvent;
import intrinsic.mx.events.ListEvent;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.flex.SWTComboBox;
import org.eclipse.swt.events.*;

public class Combo extends Composite {
	ArrayCollection dataProvider;
	
	public static final int LIMIT = 0x7fffffff;
	
public Combo (Composite parent, int style) {
	super (parent, checkStyle (style));
}

public void add (String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	dataProvider.addItem (string);
}

public void add (String string, int index) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	dataProvider.addItemAt (string, index);
}

public void addModifyListener (ModifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Modify, typedListener);
}

public void addSelectionListener (SelectionListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Selection,typedListener);
	addListener (SWT.DefaultSelection,typedListener);
}

public void addVerifyListener (VerifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Verify, typedListener);
}

static int checkStyle (int style) {
	/*
	* Feature in Windows.  It is not possible to create
	* a combo box that has a border using Windows style
	* bits.  All combo boxes draw their own border and
	* do not use the standard Windows border styles.
	* Therefore, no matter what style bits are specified,
	* clear the BORDER bits so that the SWT style will
	* match the Windows widget.
	*
	* The Windows behavior is currently implemented on
	* all platforms.
	*/
	style &= ~SWT.BORDER;
	
	/*
	* Even though it is legal to create this widget
	* with scroll bars, they serve no useful purpose
	* because they do not automatically scroll the
	* widget's client area.  The fix is to clear
	* the SWT style.
	*/
	style &= ~(SWT.H_SCROLL | SWT.V_SCROLL);
	style = checkBits (style, SWT.DROP_DOWN, SWT.SIMPLE, 0, 0, 0, 0);
	if ((style & SWT.SIMPLE) != 0) return style & ~SWT.READ_ONLY;
	return style;
}

protected void checkSubclass () {
	if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}

public void clearSelection () {
	checkWidget ();
	setSelection (getSelection ());
}

void createHandle () {
	SWTComboBox widget = new SWTComboBox();
	widget.dataProvider = dataProvider = new ArrayCollection();
	widget.editable = (style & SWT.READ_ONLY) == 0;
	object = widget;
}

public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget ();
	return computeNativeSize (object, wHint, hHint, changed);
}

public void copy () {
}

public void cut () {
}

public void deselect (int index) {
	checkWidget ();
	int selection = getSelectionIndex ();
	if (index != selection) return;
	((ComboBox)object).selectedIndex = -1;
}

public void deselectAll () {
	checkWidget ();
	int selection = getSelectionIndex ();
	if (selection == -1) return;
	((ComboBox)object).selectedIndex = -1;
}

public String getItem (int index) {
	checkWidget ();
	int count = dataProvider.length;
	if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
	return (String)dataProvider.getItemAt (index);
}

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

public int getItemHeight () {
	return 0;
}

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

public int getOrientation () {
	checkWidget ();
	return 0;
}

public Point getSelection () {
	checkWidget ();
	TextInput widget = getTextInput ();
	return new Point(widget.selectionBeginIndex, widget.selectionEndIndex);
}

public int getSelectionIndex () {
	checkWidget ();
	ListBase list = ((ComboBox)object).dropdown;
	if (list == null) return -1;
	return list.selectedIndex;
}

public String getText () {
	checkWidget ();
	return ((ComboBox)object).text;
}

public int getTextHeight () {
	return 0;
}

TextInput getTextInput() {
	return ((SWTComboBox)object).getTextInput ();
}

public int getTextLimit () {
	checkWidget ();
	int limit = getTextInput ().maxChars;
	return limit != 0 ? limit : LIMIT;
}

public int getVisibleItemCount () {
	checkWidget ();
	return ((ComboBox)object).rowCount;
}

void handleChange (intrinsic.mx.events.ListEvent event) {
	ComboBox widget = (ComboBox)object;
	if (widget.selectedIndex != -1) sendSelection ();
}

native Function handleChangeFunction ()/*{
	return handleChange__Lmx_events_ListEvent_2;
}*/;

void handleEnter (FlexEvent event) {
	postEvent (SWT.DefaultSelection); 
}

native Function handleEnterFunction ()/*{
	return handleEnter__Lmx_events_FlexEvent_2;
}*/;

void hookEvents() {
	super.hookEvents();
	object.addEventListener(FlexEvent.ENTER, handleEnterFunction ());
	object.addEventListener(ListEvent.CHANGE, handleChangeFunction ());
}

public int indexOf (String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	return dataProvider.getItemIndex(string);
}

public int indexOf (String string, int start) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	return dataProvider.toArray().indexOf (string, start);
}

public void paste () {
}

void releaseWidget () {
	super.releaseWidget ();
	dataProvider = null;
}

public void remove (int index) {
	checkWidget ();
	int count = dataProvider.length;
	if (!(0 <= index && index < count)) {
		error (SWT.ERROR_INVALID_RANGE);
	}
	dataProvider.removeItemAt (index);
}

public void remove (int start, int end) {
	checkWidget ();
	if (start > end) return;
	int count = dataProvider.length;
	if (!(0 <= start && start <= end && end < count)) {
		error (SWT.ERROR_INVALID_RANGE);
	}
	dataProvider.disableAutoUpdate();
	for (int index=end; index>=start; index--) {
		dataProvider.removeItemAt (index);
	}
	dataProvider.enableAutoUpdate();
}

public void remove (String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	int index = indexOf (string, 0);
	if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT);
	remove (index);
}

public void removeAll () {
	checkWidget ();
	dataProvider.removeAll();	
}

public void removeModifyListener (ModifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Modify, listener);	
}

public void removeSelectionListener (SelectionListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Selection, listener);
	eventTable.unhook (SWT.DefaultSelection,listener);	
}

public void removeVerifyListener (VerifyListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Verify, listener);	
}

public void select (int index) {
	checkWidget ();
	int count = dataProvider.length;
	if (0 <= index && index < count) {
		((ComboBox)object).selectedIndex = index;
	}
}

void sendSelection () {
	postEvent (SWT.Selection);
}

public void setItem (int index, String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	int count = dataProvider.length;
	if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
	dataProvider.setItemAt(string, index);
}

public void setItems (String[] items) {
	checkWidget ();
	if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
	for (int i=0; i<items.length; i++) {
		if (items [i] == null) error (SWT.ERROR_INVALID_ARGUMENT);
	}
	dataProvider.disableAutoUpdate();
	dataProvider.removeAll ();
	for (int i = 0; i < items.length; i++) {
		dataProvider.addItem (items[i]);
	}
	dataProvider.enableAutoUpdate();
}

public void setListVisible (boolean visible) {
	checkWidget ();
	if (visible) {
		((ComboBox)object).open();
	} else {
		((ComboBox)object).close();
	}
}

public void setOrientation (int orientation) {
	checkWidget ();
}

public void setSelection (Point selection) {
	checkWidget ();
	if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
	getTextInput ().setSelection (selection.x, selection.y);
}

public void setText (String string) {
	checkWidget ();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	if ((style & SWT.READ_ONLY) != 0) {
		int index = indexOf (string);
		if (index != -1) select (index);
		return;
	}
	((ComboBox)object).text = string;
}

public void setTextLimit (int limit) {
	checkWidget ();
	if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
	if (limit == LIMIT) limit = 0;
	getTextInput ().maxChars = limit;
}

public void setVisibleItemCount (int count) {
	checkWidget ();
	if (count < 0) return;
	((ComboBox)object).rowCount = count;
}

}
