dojo.provide("epages.widget.Timespinner");
dojo.require("epages.localize");
dojo.require("epages.widget");
dojo.require('epages.widget.LocalizedWidget');
dojo.require('epages.validate.date');
dojo.require("epages.uimessagehandler");
dojo.require("epages.string");
dojo.require('epages.event');

dojo.declare(
	"epages.widget.Timespinner",
	[epages.widget.LocalizedWidget],
	{

		/**
		 * public properties
		 */
		templatePath    : dojo.moduleUrl("epages.widget", "templates/Timespinner.html"),
		translationName : dojo.moduleUrl('epages', "translation"),

		delta:          5, // Integer - increment is 5 minutes by default
		value:          "",
		label:          "",
		name:           "",
		displayPattern: epages.vars.Locale.timeFormat     || "%H:%M", // String - epages time pattern
		emptyValueAllowed: true,
		initId: '',

		/**
		 * private
		 */
		_spinTimeout:           null, // timeout that holds the spinning function repetition (hold-down mouse key)
		_spinCounter:           0,    // counts the spins by the held-down mouse key to determine spinning speed
		_delta:                 0,    // this.delta in millisecs
		_spinIntervalFunction:  null, // function reference of the spinning function

		postMixInProperties: function() {
			if (typeof this.delta == 'string'){
				this.delta = new Number(this.delta);
			}
			if (this.delta<=0){
				this.delta = this.prototype.delta;
			}
			this._delta = this.delta * 60000; // calculate private delta, from mins to millisec
			this.emptyValueAllowed = epages.string.toBoolean(this.emptyValueAllowed);
		},

		postCreate: function() {
			// set initial value
			if (this.value != '') {
				var date = this.value;
				this.value = null;
				this.setValue(date);
			} else if (! this.emptyValueAllowed){
				// default is noon
				var date = new Date();
				date.setTime(43200000 + date.getTimezoneOffset() * 60000);
				this.value = null;
				this.setValue(date);
			} else {
				this.value = null;
			}

			this.connect(this.timeNode,   'focus', 'onFocus');
			this.connect(this.timeNode,   'blur', 'onBlur');

			// 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');
		},

		onFocus: function() {
			dojo.addClass(this.domNode, "Focus");
		},

		onBlur: function() {
			dojo.removeClass(this.domNode, "Focus");
		},

		getValue: function() {
			// summary:
			//    returns the value as a date object, day is 1970-01-01
			return this.value;
		},

		setValue: function(/*Date*/date, /* booleab */ skipDisplay) {
			// summary:
			//    sets the time of Date into inputNode value and the internal property

			if (date === undefined){
				date = new Date();
			}
			else if (typeof date == "string") {
				date = epages.string.toTime(date, this.displayPattern);
				if(this.value) {	// fill up year, month, day
					date.setFullYear(this.value.getFullYear());
					date.setMonth(this.value.getMonth());
					date.setDate(this.value.getDate());
				}
			}
			if(!this.value || dojo.date.compare(date, this.value)){
				this.value = new Date(date);
				if(! skipDisplay){
					this.timeNode.value = epages.localize.formatDateTime(date, this.displayPattern);
				}
			}
			dojo.removeClass(this.timeNode, "DialogError");
			dojo.publish("uimessage/hide", []);
			dojo.publish(this.id + '/onChange', [date]);
		},

		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.timeNode, 'change');
			}
			this._spinCounter = 0;
			window.clearTimeout(this._spinTimeout);
		},

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

			// only spin, if date and direction are valid
			if (direction == 0){
				return;
			}
			var isValueChanged = false;

			if (this.value == null && this.timeNode.value != '') {
				var w = $$(this.initId);
				if (w) {
					this.value = w.value;
					isValueChanged = true;
				}
			}
			if (this.value == null && this.initId != '') {
				var w = $$(this.initId);
				if (w) {
					this.value = w.value;
					isValueChanged = true;
				}
			}
			if (this.value == null) {
				this.value = dojo.date.locale.parse('0', { selector: 'date', datePattern: 'HH', timePattern: '' });
				isValueChanged = true;
			}
			var date = new Date(this.value);
			if (isValueChanged){
				this.value=null;
			}else{ // set time via UTC in millisec - ensure that direction is either 1 or -1
				date.setTime(this.value.getTime() + this._delta * (direction / Math.abs(direction)));
			}

			this.setValue(date);
		},

		_onKeyUp: function(evt) {
			var newValue = evt.target.value;
			var isValid = epages.validate.date.isTime(newValue, this.displayPattern);
			if(isValid === true) {
				this.setValue(newValue, true);
			} else if(isValid == "NO_VALUE" && this.emptyValueAllowed) {
				dojo.removeClass(this.timeNode, "DialogError");
				dojo.publish("uimessage/hide", []);
				this.value = null;
			} else {
				dojo.addClass(this.timeNode, "DialogError");
			}
		},

		_onChange: function(evt) {
			//set 'px' as default-unit
			var newValue = evt.target.value;
			var isValid = epages.validate.date.isTime(newValue, this.displayPattern);

			var position=$E(this.timeNode).getRelativePosition();

			if(isValid != true && ! (isValid == "NO_VALUE" && this.emptyValueAllowed)) {
				//display Error-Box-Widget
				dojo.publish("uimessage/show", ["", this.translation.get(isValid), "Bubble", {
					typeClass: "Warning",
					sizeClass: "Small",
					x: position.x,
					y: position.y + this.timeNode.clientHeight + 4,
					attachNode: this.domNode.parentNode
				}]);
			}
		}
	}
);