/*******************************************************************************
 * 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 java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;

import com.google.gwt.core.client.*;

public class Combo extends Composite {

ArrayList items = new ArrayList ();
Object jsItems;

public Combo (Composite parent, int style) {
	super (parent, checkStyle (style));
}

public void add (String string) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	add (string, items.size());
}

public void add (String string, int index) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (!(0 <= index && index <= items.size())) {
		error (SWT.ERROR_INVALID_RANGE);
	}
	items.add(index, string);
	//TODO: e4 use JsArrayString instead of ArrayList in order not to have two arrays
	JsArrayString jsarray = (JsArrayString) JavaScriptObject.createArray();
	for (int i = 0; i < items.size(); i++) {
		jsarray.set(i, (String) items.get(i));
	}
	_updateStore(jsarray);
}

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 () {
}

public void clearSelection () {
}

public Point computeSize (int wHint, int hHint, boolean changed) {
//TODO make use of changed
	Rectangle rectangle = getNativeBounds();
	int width = rectangle.width;
	int height = rectangle.height;
	if (wHint != SWT.DEFAULT) width = wHint;
	if (hHint != SWT.DEFAULT) height = hHint;
	return new Point (width, height);
}

public void copy () {
}

public void cut () {
}

public void deselect (int index) {
}

public void deselectAll () {
}

public String getItem (int index) {
	checkWidget();
	if (!(0 <= index && index < items.size())) {
		error (SWT.ERROR_INVALID_RANGE);
	}
	return (String) items.get(index);
}

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

public int getItemHeight () {
	return 0;
}

public String[] getItems () {
	checkWidget();
	return (String []) items.toArray(new String[items.size()]);
}

public int getOrientation () {
	return 0;
}

public Point getSelection () {
	return null;
}

public int getSelectionIndex () {
	checkWidget();
	if (items.isEmpty()) return -1;
	return _getSelectionIndex();
}

public String getText () {
	return _getText();
}

public int getTextHeight () {
	return 0;
}

public int getTextLimit () {
	return 0;
}

public int getVisibleItemCount () {
	return 0;
}

void hookEvents () {
	super.hookEvents();
	_hookCalls("_doSelect", SWT.Selection);
}

public int indexOf (String string) {
	return 0;
}

public int indexOf (String string, int start) {
	return 0;
}

public void paste () {
}

public void remove (int index) {
}

public void remove (int start, int end) {
}

public void remove (String string) {
}

public void removeAll () {
}

public void removeModifyListener (ModifyListener listener) {
}

public void removeSelectionListener (SelectionListener listener) {
}

public void removeVerifyListener (VerifyListener listener) {
}

public void select (int index) {
	checkWidget();
	if (index < 0 || index >= items.size()) return;
	_select(index);
}

public void setFont (Font font) {
}

public void setItem (int index, String string) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (!(0 <= index && index < items.size())) {
		error (SWT.ERROR_INVALID_ARGUMENT);
	}
	items.set(index, string);
	JsArrayString jsarray = (JsArrayString) JavaScriptObject.createArray();
	for (int i = 0; i < items.size(); i++) {
		jsarray.set(i, (String) items.get(i));
	}
	_updateStore(jsarray);
}

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);
	}
	ArrayList temp = new ArrayList(items.length);
	for (int i = 0; i < items.length; i++) {
		temp.add(items[i]);
	}
	this.items = temp;
	JsArrayString jsarray = (JsArrayString) JavaScriptObject.createArray();
	for (int i = 0; i < this.items.size(); i++) {
		jsarray.set(i, (String) this.items.get(i));
	}
	_updateStore(jsarray);
}

public void setOrientation (int orientation) {
}

public void setSelection (Point selection) {
	_setSelection (selection);
}

public void setText (String string) {
	_setText(string);
}

public void setTextLimit (int limit) {
}

public void setVisibleItemCount (int count) {
}

/*---------------- NATIVE INTERFACE ----------------*/

protected native void _createHandle (Widget parent, int style, int index) /*-{
	if((style & (@org.eclipse.swt.SWT::DROP_DOWN | @org.eclipse.swt.SWT::READ_ONLY)) != 0){
		if(!$wnd.dojo._hasResource["org.eclipse.swt.DropDownCombo"]){
			$wnd.dojo._hasResource["org.eclipse.swt.DropDownCombo"] = true;
			$wnd.dojo.provide("org.eclipse.swt.DropDownCombo");
			
			$wnd.dojo.require("dojo.data.ItemFileWriteStore");
			$wnd.dojo.require("dijit.form.ComboBox");
		
			$wnd.dojo.declare("org.eclipse.swt.DropDownCombo", $wnd.dijit.form.ComboBox, {
				_arrowMargin: "",
				_minWidth: 35,
				_readOnly: false,
				autoComplete: false,
				jObject: "",
				constructor: function(){
					this.store = new $wnd.dojo.data.ItemFileWriteStore({data: {items: []}});
					this._popupWidget = new $wnd.dijit.form._ComboBoxMenu({
						onChange: $wnd.dojo.hitch(this, this._selectOption)
					})
					this._arrowSize = {w: 0,h: 0};
					jObject = {};
					this.@org.eclipse.swt.widgets.Combo::jsItems = [];
				},
				_startSearchFromInput: function(){},
				getNativeBounds: function(){
					var dnLoc = $wnd.swt.getNativeLocation(this.domNode);
					$wnd.dojo.query(".dijitMenuItem",this._popupWidget.domNode).removeClass("dijitMenuItem");
					var pwSize = $wnd.swt.getNativeSize(this._popupWidget.domNode);
					var tbSize = $wnd.swt.getNativeSize(this.textbox);
					return {l:dnLoc.l, t:dnLoc.t, w:Math.max(pwSize.w,tbSize.w)+this._arrowSize.w, h:this._arrowSize.h};
				},
				postCreate: function(){
					this.inherited("postCreate",arguments);
					this.textbox.readOnly = this._readOnly;
					$wnd.dojo.query(".dijitValidationIcon",this.domNode).style("width","0px");
					$wnd.swt.setCssStyle(this._popupWidget.previousButton, {display: "none"});
					$wnd.swt.setCssStyle(this._popupWidget.nextButton, {display: "none"});
					this._arrowSize.w = $wnd.swt.getNativeBounds(this.downArrowNode).w + 10;
					this._arrowSize.h = $wnd.swt.getNativeBounds(this.downArrowNode.firstChild).h;
					$wnd.swt.setNativeBounds(this.domNode, {w: 0, h: this._arrowSize.h});
				},			
				_onKeyPress: function(evt){
//TODO implement PAGE_DOWN, PAGE_UP, DOWN_ARROW, UP_ARROW key events
				},
				resize: function(){},
				setWidgetBounds: function(dim){
					$wnd.swt.setBounds(this.domNode, {
						w: Math.max(dim.w, this._minWidth), 
						t: dim.t, 
						l: dim.l
					});
				}
			});
		}
	}
	if((style & (@org.eclipse.swt.SWT::SIMPLE)) != 0){	
		if(!$wnd.dojo._hasResource["org.eclipse.swt.SimpleCombo"]){
			$wnd.dojo._hasResource["org.eclipse.swt.SimpleCombo"] = true;
			$wnd.dojo.provide("org.eclipse.swt.SimpleCombo");
			
			$wnd.dojo.require("dijit.form._FormWidget");
			$wnd.dojo.require("dijit.form.TextBox");
		
			$wnd.dojo.declare("org.eclipse.swt.SimpleCombo", $wnd.dijit.form._FormWidget, {
				baseClass: "swtCombo",
				border: "",
				templateString: '<div class="${baseClass} swtComposite swtControl" baseClass="${baseClass}" dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse" id="${id}">' +
									'<div dojoAttachPoint="focusNode,textbox"></div>' +
									'<div dojoAttachPoint="containerNode"></div>' +
								'</div>',
				addItem: function(item){
					var menuitem = this.menu._createOption(item, function(item){return item;});
					menuitem.className = "swtComboItem"
					$wnd.dojo.addClass(menuitem, "dijitMenuItem");
					$wnd.dojo.place(menuitem, this.menu.domNode, item.index+1);
				},
				buildRendering: function(){
					this.inherited("buildRendering", arguments);
					this.textbox = new $wnd.dijit.form.TextBox({}, this.textbox);
					$wnd.swt.setCssStyle(this.textbox.domNode,{margin: "0px"});
					this.focusNode = this.textbox.domNode;
					this.menu = new $wnd.dijit.form._ComboBoxMenu({}, this.containerNode);
					var self = this;
					this.menu.setValue = function(value){
						self.menu.value = value;
						self.setValue(value.target.item.label);
						self.onChange(value);
					};
					this.containerNode = this.menu.domNode;
					$wnd.dojo.addClass(this.containerNode,"swtScrollable");
					$wnd.dojo.addClass(this.containerNode,"dijitMenuSeparator");
				},
				getItemValue: function(index){
//TODO implement				
				},
				getNativeBounds: function(){
					var dnLoc = $wnd.swt.getNativeLocation(this.domNode);
					var fnSize = $wnd.swt.getNativeSize(this.focusNode);
					var cnHeight = $wnd.swt.getNativeSize(this.containerNode).h;
					$wnd.dojo.query(".swtComboItem",this.menu.domNode).removeClass("dijitMenuItem");
					var cnWidth = $wnd.swt.getNativeSize(this.containerNode).w;
					$wnd.dojo.query(".swtComboItem",this.menu.domNode).addClass("dijitMenuItem");
					return {l:dnLoc.w, t:dnLoc.t, w:Math.max(fnSize.w,cnWidth)+10, h:fnSize.h+cnHeight+10};	
				},
				postCreate: function(){
					this.inherited("postCreate", arguments);
					$wnd.swt.setCssStyle(this.domNode, {border: this.border});
					$wnd.swt.setCssStyle(this.menu.previousButton, {display: "none"});
					$wnd.swt.setCssStyle(this.menu.nextButton, {display: "none"});
				},
				setValue: function(value){
					this.textbox.setValue(value);
				},
				setWidgetBounds: function(dim){
					$wnd.swt.setBounds(this.textbox.domNode, {
						w: $wnd.swt.setBounds(this.domNode, {w:dim.w, t:dim.t ,l:dim.l}).w
					});
					$wnd.swt.setBounds(this.containerNode, {
						w: dim.w, 
						h: Math.max(dim.h-$wnd.swt.getNativeBounds(this.textbox.domNode,true).h,0)
					});
				}
			});
		}
	}
	
	var jsParent = parent.@org.eclipse.swt.widgets.Widget::jsObject;
	var params = {};
	if((style & (@org.eclipse.swt.SWT::DROP_DOWN | @org.eclipse.swt.SWT::READ_ONLY)) != 0){
		if((style & (@org.eclipse.swt.SWT::READ_ONLY)) != 0){
			params._readOnly = true;
		}
		params.jObject = this;
		var self = new $wnd.org.eclipse.swt.DropDownCombo(params);
	}
	else if((style & (@org.eclipse.swt.SWT::SIMPLE)) != 0){
		var self = new $wnd.org.eclipse.swt.SimpleCombo(params);
	}
	try {
		this.@org.eclipse.swt.widgets.Widget::jsObject = self;
		jsParent.addChild(self);
	} catch (e) {
//TODO Have to throw real exception for Java side also	
		$wnd.console.log(e);
	}
}-*/;

native int _getSelectionIndex() /*-{	
	var item = this.@org.eclipse.swt.widgets.Widget::jsObject.item;
	if (item === null) return -1;
	return parseInt(item.index);
	
}-*/;

native String _getItem(int index) /*-{
	return this.@org.eclipse.swt.widgets.Widget::jsObject.getItemValue(index);
}-*/;

native String _getText() /*-{
	return this.@org.eclipse.swt.widgets.Widget::jsObject.getValue();
}-*/;

native void _setText (String string) /*-{
	this.@org.eclipse.swt.widgets.Widget::jsObject.setValue(string);
}-*/;

native void _select (int index) /*-{
	var selectedItem = this.@org.eclipse.swt.widgets.Combo::jsItems[index];
	this.@org.eclipse.swt.widgets.Widget::jsObject.item = selectedItem;
	this.@org.eclipse.swt.widgets.Widget::jsObject.setValue(selectedItem.name);
}-*/;

native void _setSelection (Point selection) /*-{
//TODO	
}-*/;

native void _updateStore (JsArrayString strings) /*-{
	var options = new $wnd.dojo.data.ItemFileWriteStore({data: {identifier: 'name', items:[]}});
	var items = this.@org.eclipse.swt.widgets.Combo::jsItems = new Array(strings.length);
	for (i=0;i<strings.length;i++) {
		items[i] = options.newItem({name: strings[i], index: i});
	}
	this.@org.eclipse.swt.widgets.Widget::jsObject.store = options;
}-*/;


}
