/*
	Copyright (c) 2006-2009, ePages GmbH
	All Rights Reserved.
*/
dojo.provide('epages.widget.NumberSpinner');
dojo.require('dijit._Widget');
dojo.require('dijit._Templated');
dojo.require('epages.localize');
dojo.require('epages.event');
dojo.require('epages.string');

dojo.declare("epages.widget.NumberSpinner",
	[dijit._Widget,dijit._Templated], {

/**
 * public properties
 */
	name         : "",
	value        : "",				// String - parameter start value
	minValue     : "0",				// String - parameter minimal value, no spinning under this value
	maxValue     : Number.MAX_VALUE.toString(),				// String - parameter maximal value, no spinning upper this value
	delta        : "0",				// String - parameter for counting steps
	trimInterval : "false",		// String - trim value to next interval step
	unit         : "",				// String - parameter for number devices
/**
 * private
 */
	_spinTimeout:           null, // windowTimoutHandle  timeout that holds the spinning function repetition (hold-down mouse key)
	_spinCounter:           0,    // Integer - counts the spins by the held-down mouse key to determine spinning speed
	_spinIntervalFunction:  null, // function - reference of the spinning function

/**
 * widget properties
 */
	templatePath : dojo.moduleUrl("epages.widget", "templates/NumberSpinner.html"),

	postCreate : function() {
		this.inherited("postCreate", arguments);
		// variables to fade in and out the number devices
		var borderWidth = this.fakeNode.clientLeft; 		// set var to element left border
		var left = borderWidth+40;											// set var from left (border + 40px)
		var borderHeight = this.fakeNode.clientTop;			// set var to element top border
		this.containerNode.style.top=borderHeight+"px";	// set top border to element
		this.unitNode.style.left=left+"px";							// set distance from left
		// show element with css, if set the variable
		if(this.unit != "") {
			this.unitNode.style.display="";
		}
		// calculate the fake input element width
		var width = this.unitNode.clientWidth + 40;
		this.fakeNode.style.width=width+"px"; // set input container width if unit is displayed

		// button user functions
		this.connect(this.inputNode, 'onkeyup', 'onKeyUp');

		// round time to closest possible position
		this.connect(this.upNode,   'mouseup', 'onMouseUp');
		this.connect(this.downNode, 'mouseup', 'onMouseUp');
		this.connect(this.upNode,   'mouseout', 'onMouseUp');
		this.connect(this.downNode, 'mouseout', 'onMouseUp');
		this.connect(this.upNode,   'mousedown', 'onMouseDown');
		this.connect(this.downNode, 'mousedown', 'onMouseDown');

		this.value = epages.localize.parseNumber(this.value);
		this.minValue = epages.localize.parseNumber(this.minValue);
		this.maxValue = epages.localize.parseNumber(this.maxValue);
		this.delta = epages.localize.parseNumber(this.delta);

		if(isNaN(this.value)) {
			console.warn("Value is not a Number in "+this.declaredClass);
		}

		if(isNaN(this.minValue)) {
			console.warn("minValue is not a Number in "+this.declaredClass);
		}

		if(isNaN(this.maxValue)) {
			console.warn("maxValue is not a Number in "+this.declaredClass);
		}

		if(this.value < this.minValue) {
			this.value = this.minValue ;
			this.updateInputNode();
			console.warn("value is smaller than minValue "+this.declaredClass);
		}

		if(this.value > this.maxValue) {
			this.value = this.maxValue ;
			this.updateInputNode();
			console.warn("value is larger than maxValue "+this.declaredClass);
		}

		this.trimInterval = epages.string.toBoolean(this.trimInterval);
	},

	updateInputNode : function() {
		this.inputNode.value = epages.localize.formatNumber(this.value);
	},

	spin : function(/* integer */ direction) {
		// summary:
		//    spin the value by delta
		// direction: 
		//   | if > 0, spin up
		//   | if < 0, spin down
		//   | if = 0, do nothing

		// only spin, if number and direction are valid
			if (direction == 0){
				return;
			}

			if (direction > 0) {
				if(this.trimInterval) {
					// add and trim delta to interval
					var value = this.value + this.delta;
					var factor = Math.round((value-this.minValue)/this.delta);
					this.value = this.minValue+factor*this.delta;
				} else {
					// just add delta
					this.value = this.value + this.delta;
				}
				if (this.value > this.maxValue ) {
						this.value = this.maxValue;
				}  // endif check maxValue
			} else if (direction < 0) {
					if(this.trimInterval) {
						// substract and trim delta to interval
						var value = this.value - this.delta;
						var factor = Math.round((value-this.minValue)/this.delta);
						this.value = this.minValue+factor*this.delta;
					} else {
						// just substract delta from value
							this.value = this.value - this.delta;
					} // endif trim to interval

					if (this.value < this.minValue ) {
							this.value = this.minValue;
					}  // endif check minValue
			}
			this.updateInputNode();
	},

	onMouseDown: function(evt) {
		// summary:
		//    handle mousedowns on the spinner arrows
		var direction;
		if (evt.target == this.upNode) {
			direction = 1;
		} else if(evt.target == this.downNode) {
			direction = -1;
		} else {
			return;
		}
		this._spinIntervalFunction = dojo.hitch(this, function() {
			var speed = this._spinCounter > 5 ? this._spinCounter > 25 ? 25 : 55 : 200;
			this.spin(direction);
			this._spinCounter++;
			window.clearTimeout(this._spinTimeout);
			this._spinTimeout = undefined;
			this._spinTimeout = window.setTimeout(this._spinIntervalFunction, speed);
		});
		this._spinIntervalFunction();
	},

	onMouseUp: function() {
		// summary:
		//    stop spinning
		if(this._spinCounter){
			epages.event.fire(this.inputNode, 'change');
		}
		this._spinCounter = 0;
		window.clearTimeout(this._spinTimeout);
	},

	valueUp : function(){
		// summary: Count inputNode value up
		this.spin(1);
	},

	valueDown : function() {
		this.spin(-1);
	},

	onKeyUp : function() {
		// summary: pass input value changes to widget value on keyup
		var value = epages.localize.parseNumber(this.inputNode.value);
		if(isNaN(value)) {
			console.warn("Value is not a Number in onKeyup in "+this.declaredClass);
		} else {
			this.value = value;
		}
	}

});