/*******************************************************************************
 * 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 org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.events.*;

public class Spinner extends Composite {
	int digits = 0, minimum = 0, maximum = 100, selection = 0, increment = 1, pageIncrement = 100;

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

static int checkStyle (int style) {
	/*
	* 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.
	*/
	return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
}

//TODO
protected void checkSubclass () {
}

//TODO
public void addModifyListener (ModifyListener listener) {
}

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 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);
}

//TODO
public void copy () {
}

void createWidget (Display display, Widget parent, int style, int index) {
	super.createWidget (display, parent, style, index);
	this.setValues(selection, minimum, maximum, digits, increment, pageIncrement);
}

//TODO
public void cut () {
}

public int getDigits () {
	checkWidget ();
	return digits;
}

public int getIncrement () {
	checkWidget ();
	return increment;
}

public int getMaximum () {
	checkWidget ();
	return maximum;
}

public int getMinimum () {
	checkWidget ();
	return minimum;
}

public int getPageIncrement () {
	checkWidget ();
	return pageIncrement;
}

public int getSelection () {
	checkWidget ();
	return selection;
}

void hookEvents () {
	super.hookEvents();
	_hookEvents("onclick", SWT.Selection);
	_hookSetValue("_arrowPressed");
}

//TODO
public void paste () {
}

//TODO
public void removeModifyListener (ModifyListener 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);	
}

//TODO setDigits will configure to increment the last number with increment,
//not actually the case with Dojo
public void setDigits (int value) {
	if(value==this.digits) return;
	setValues(selection, minimum, maximum, value, increment, pageIncrement);
}

public void setIncrement (int value) {
	if(value==this.increment) return;
	setValues(selection, minimum, maximum, digits, value, pageIncrement);
}

public void setMaximum (int value) {
	if(value==this.maximum) return;
	setValues(selection, minimum, value, digits, increment, pageIncrement);
}

public void setMinimum (int value) {
	if(value==this.minimum) return;
	setValues(selection, value, maximum, digits, increment, pageIncrement);
}

public void setPageIncrement (int value) {
	if(value==this.pageIncrement) return;
	setValues(selection, minimum, maximum, digits, increment, value);
}

public void setSelection (int value) {
	if(value==this.selection) return;
	setValues(value, minimum, maximum, digits, increment, pageIncrement);
}

public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
	checkWidget ();
	if (maximum <= minimum) return;
	if (digits < 0) return;
	if (increment < 1) return;
	if (pageIncrement < 1) return;
	selection = Math.min (Math.max (minimum, selection), maximum);
	this.selection = selection;
	this.minimum = minimum;
	this.maximum = maximum;
	this.digits = digits;
	this.increment = increment;
	this.pageIncrement = pageIncrement;
	_setValues(selection, minimum, maximum, digits, increment, pageIncrement);
}

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

protected native void _createHandle (Widget parent, int style, int index) /*-{
	if(!$wnd.dojo._hasResource["org.eclipse.swt.Spinner"]){
		$wnd.dojo._hasResource["org.eclipse.swt.Spinner"] = true;
		$wnd.dojo.provide("org.eclipse.swt.Spinner");
		
		$wnd.dojo.require("dijit.form.NumberSpinner");
		
		$wnd.dojo.declare("org.eclipse.swt.Spinner", $wnd.dijit.form.NumberSpinner, {
			_readOnly: false,
			border: "1px solid #B3B3B3",
			selection: 0,
			_arrowPressed: function(nodePressed, direction){
				if(this.disabled){ return; }
				$wnd.dojo.addClass(nodePressed, "dijitSpinnerButtonActive");
			},
			getNativeBounds: function(){
				var dnLoc = $wnd.swt.getNativeLocation(this.domNode);
				var dnPadBorderExtends = $wnd.dojo._getPadBorderExtents(this.domNode);
				var aN = $wnd.swt.getNativeSize(this.upArrowNode);
				var fnSize = $wnd.swt.getNativeSize(this.focusNode);
				return {l:dnLoc.w, t:dnLoc.t, w:fnSize.w+aN.w+dnPadBorderExtends.w, h:fnSize.h+dnPadBorderExtends.h};
			},
			postCreate: function(){
				this.inherited("postCreate",arguments);
				this.textbox.readOnly = this._readOnly;
				$wnd.swt.setNativeBounds(this.domNode, {w: 0, h: 0});
				$wnd.swt.setCssStyle(this.domNode, {
					border: this.border,
					margin: "0 0 0 0"
				});
				$wnd.dojo.query(".dijitValidationIcon",this.domNode).style("width","0px");
			},
			resize: function(dim){},			
			setWidgetBounds: function(dim){
				var dnDim = $wnd.swt.setBounds(this.domNode, dim);
				var arrowHeight = dnDim.h/2+"px";
				$wnd.dojo.query(".dijitInputLayoutContainer",this.domNode).style("height",dnDim.h+"px");
				$wnd.dojo.query(".dijitSpinnerButtonContainer",this.domNode).style("height",dnDim.h+"px");
				$wnd.dojo.query(".dijitArrowButton*",this.domNode).forEach(
				    function(node) {$wnd.swt.setCssStyle(node, {height: arrowHeight,lineHeight: arrowHeight});}
				);
			},
			update: function(args) {
				var places = this.constraints.places;
				this.constraints={
					min:args.min,
					max:args.max,
					places:args.places
				}
				this.smallDelta=args.smallDelta;
				this.largeDelta=args.largeDelta;
				this.setValue(args.value);
			}
		});
	}
	
	var jsParent = parent.@org.eclipse.swt.widgets.Widget::jsObject;
	params = {};
	if((style & (@org.eclipse.swt.SWT::BORDER)) != 0){
		params.border = "1px solid black";
	}
	if((style & (@org.eclipse.swt.SWT::READ_ONLY)) != 0){
		params._readOnly = true;
	}
	if((style & (@org.eclipse.swt.SWT::WRAP)) != 0){
	}
	var self = new $wnd.org.eclipse.swt.Spinner(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 void _hookSetValue (String eventType) /*-{
	var self = this;
	$wnd.dojo.connect(
		self.@org.eclipse.swt.widgets.Widget::jsObject,
		eventType,
		function(nodePressed, direction){
			var _self = self.@org.eclipse.swt.widgets.Widget::jsObject;
			var value = (_self.getValue()*Math.pow(10,_self.constraints.places)) + (direction*_self.smallDelta);
			self.@org.eclipse.swt.widgets.Spinner::setSelection(I)(value);
		}
	);
}-*/;

native void _setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) /*-{
	var div = Math.pow(10,digits);
	this.@org.eclipse.swt.widgets.Widget::jsObject.update({
		value: selection/div,
		min: minimum/div,
		max: maximum/div,
		places: digits,
		smallDelta: increment,
		largeDelta: pageIncrement
	});
}-*/;

}
