/**
  * A cross-browser datepicker widget.
  *
  * Copyright (c) 2004,2005,2006 Troels Knak-Nielsen
  *
  * License: LGPL
  *
  * Version : 18. mar 2006
  */
jx.Widget.DatePicker = function(args) {
	this.superconstructor.apply(this, arguments);
	if (args) {
		this.mode = (args.mode) ? args.mode : jx.Widget.DatePicker.MODE_DATE;
	}

	// default values to start out with
	this.setValue(new Date());
	this.startYear = this.date.getRealYear() - 50;
	this.endYear = this.date.getRealYear() + 10;
};
jx.Class.extend(jx.Widget.DatePicker, jx.Widget.Base);

jx.Widget.DatePicker.MODE_DATE = 1;
jx.Widget.DatePicker.MODE_DATE_TIME = 2;
jx.Widget.DatePicker.MODE_DATE_TIME_SECONDS = 3;
jx.Widget.DatePicker.i18n = {};
jx.Widget.DatePicker.i18n.months = [
	"January", "February", "March", "April", "May", "June", "July",
	"August", "September", "October", "November", "December"
];

jx.Widget.DatePicker.prototype.setValue = function(d) {
	var extendDate = function(obj) {
		if (obj._extendedDate) return obj;
		obj.getRealYear = function() {
			if (this.getFullYear) {
				return parseInt(this.getFullYear());
			} else {
				var y = parseInt(this.getYear());
				if (y < 100) return y + 1900;
			}
			return y;
		};
		obj.setFromString = function(s) {
			var pattern = new RegExp("^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$");
			if (!s.match(pattern)) {
				throw new Error("Input string must be ISO 8601 formated date");
			}
			var matches = pattern.exec(s);
			if (this.setFullYear) {
				this.setFullYear(matches[1]);
			} else {
				this.setYear(matches[1]);
			}
			this.setMonth(matches[2] - 1);
			this.setDate(matches[3]);
			this.setHours(matches[4]);
			this.setMinutes(matches[5]);
			this.setSeconds(matches[6]);
		}
		obj._extendedDate = true;
		return obj;
	}

	if (d instanceof Date) {
		if (!d._extendedDate) {
			this.date = extendDate(d);
		} else {
			this.date = d;
		}
	} else {
		this.date = extendDate(new Date());
		this.date.setFromString(d);
	}
	if (this.date.getRealYear() < this.startYear) this.startYear = this.date.getRealYear();
	if (this.date.getRealYear() > this.endYear) this.endYear = this.date.getRealYear();
};

/**
  * Returns an ISO formatted datetime-string
  */
jx.Widget.DatePicker.prototype.getValue = function() {
	var intToString = function(n) {
		if (n  < 10) return "0" + n;
		else return "" + n;
	};
	var str = this.date.getRealYear() + "-" + intToString(this.date.getMonth()+1) + "-" + intToString(this.date.getDate());
	if (this.mode == jx.Widget.DatePicker.MODE_DATE_TIME) {
		str += " " + intToString(this.date.getHours()) + ":" + intToString(this.date.getMinutes()) + ":00";
	} else 	if (this.mode == jx.Widget.DatePicker.MODE_DATE_TIME_SECONDS) {
		str += " " + intToString(this.date.getHours()) + ":" + intToString(this.date.getMinutes()) + ":" + intToString(this.date.getSeconds());
	}
	return str;
};

jx.Widget.DatePicker.prototype.attach = function(elm) {
	this.view = {};

	this.view.field = elm;
	if (elm.type.toLowerCase() != "hidden") {
		elm.style.display = "none";
	}
	this.setValue(this.view.field.value);

	var extendSelect = function(obj) {
		obj._removeItem = function(value) {
			var len = this.length;
			for (var i=0; i<len ; i++) {
				if (this.options[i] != null) {
					if (this.options[i].value == value) {
						this.options[i] = null;
						return true;
					}
				}
			}
			return false;
		};

		obj._addItem = function(value, key) {
			this._removeItem(value);
			if (!key) key = value;
			this.options[this.length] = new Option(key, value);
		};

		obj._selectItem = function(value) {
			var len = this.length;
			for (var i=0; i<len ; i++) {
				if (this.options[i].value == value) {
					this.options[i].selected = true;
					return true;
				}
			}
			return false;
		};

		obj._getSelectedValue = function() {
			return this.options[this.selectedIndex].value;
		};
		return obj;
	};

	var container = document.createElement("DIV");
	this.view.container = container;
	this.view.field.parentNode.insertBefore(container, this.view.field);

	this.view.inputs = {};
	this.view.inputs.day = extendSelect(document.createElement("SELECT"));
	this.view.inputs.day.style.width = "4em";
	for (var i=1; i <= 31; i++) {
		var option = document.createElement("OPTION");
		option.setAttribute("value", i);
		option.appendChild(document.createTextNode(i));
		this.view.inputs.day.appendChild(option);
	}
	this.view.container.appendChild(this.view.inputs.day);
	this.connect(this.view.inputs.day, "onchange", bind(this.viewChanged, this));
	this.view.inputs.day._selectItem(this.date.getDate());

	this.view.container.appendChild(document.createTextNode(" "));

	this.view.inputs.month = extendSelect(document.createElement("SELECT"));
	for (var i=1; i <= 12; i++) {
		var option = document.createElement("OPTION");
		option.setAttribute("value", i);
		option.appendChild(document.createTextNode(jx.Widget.DatePicker.i18n.months[i-1]));
		this.view.inputs.month.appendChild(option);
	}
	this.view.container.appendChild(this.view.inputs.month);
	this.connect(this.view.inputs.month, "onchange", bind(this.viewChanged, this));
	this.view.inputs.month._selectItem(this.date.getMonth()+1);

	this.view.container.appendChild(document.createTextNode(" "));

	this.view.inputs.year = extendSelect(document.createElement("SELECT"));
	this.view.inputs.year.style.width = "5em";
	for (var i = this.startYear; i <= this.endYear; i++) {
		var option = document.createElement("OPTION");
		option.setAttribute("value", i);
		option.appendChild(document.createTextNode(i));
		this.view.inputs.year.appendChild(option);
	}
	this.view.container.appendChild(this.view.inputs.year);
	this.connect(this.view.inputs.year, "onchange", bind(this.viewChanged, this));
	this.view.inputs.year._selectItem(this.date.getRealYear());

	if (this.mode == jx.Widget.DatePicker.MODE_DATE_TIME || this.mode == jx.Widget.DatePicker.MODE_DATE_TIME_SECONDS) {
		var keyDownHandler = function(event) {
			var flag = false;
			if (event.key().code == 40) {
				this.value = parseInt(parseFloat(this.value)) - 1;
				signal(this, "onchange");
				flag = true;
			}
			if (event.key().code == 38) {
				this.value = parseInt(parseFloat(this.value)) + 1;
				signal(this, "onchange");
				flag = true;
			}
			if (event.key().code == 34) {
				this.value = parseInt(parseFloat(this.value)) - 10;
				signal(this, "onchange");
				flag = true;
			}
			if (event.key().code == 33) {
				this.value = parseInt(parseFloat(this.value)) + 10;
				signal(this, "onchange");
				flag = true;
			}

			if (flag) {
				try {
					if (document.selection && document.selection.createRange) { // ie
						var txtrange = this.createTextRange();
						txtrange.moveStart("character", 0);
						txtrange.select();
					} else {
						this.selectionStart = 0;
						this.selectionEnd = this.value.length;
					}
				} catch (ex) {}
				event.stop();
			}
		};

		this.view.container.appendChild(document.createTextNode(" "));
		if (window.innerHeight) {
			this.view.inputs.hour = document.createElement("INPUT");
			this.view.inputs.hour.setAttribute("type", "text");
		} else {
			this.view.inputs.hour = document.createElement("<INPUT type='text'>");
		}
		this.view.inputs.hour.setAttribute("size", 2);
		this.view.inputs.hour.setAttribute("maxlength", 2);
		this.view.inputs.hour.style.width = "2em";
		this.view.container.appendChild(this.view.inputs.hour);
		this.connect(this.view.inputs.hour, "onchange", bind(this.viewChanged, this));
		this.connect(this.view.inputs.hour, "onkeydown", bind(keyDownHandler, this.view.inputs.hour));
		this.view.inputs.hour.value = this.date.getHours();

		this.view.container.appendChild(document.createTextNode(" "));
		if (window.innerHeight) {
			this.view.inputs.minute = document.createElement("INPUT");
			this.view.inputs.minute.setAttribute("type", "text");
		} else {
			this.view.inputs.minute = document.createElement("<INPUT type='text'>");
		}
		this.view.inputs.minute.setAttribute("size", 2);
		this.view.inputs.minute.setAttribute("maxlength", 2);
		this.view.inputs.minute.style.width = "2em";
		this.view.container.appendChild(this.view.inputs.minute);
		this.connect(this.view.inputs.minute, "onchange", bind(this.viewChanged, this));
		this.connect(this.view.inputs.minute, "onkeydown", bind(keyDownHandler, this.view.inputs.minute));
		this.view.inputs.minute.value = this.date.getMinutes();

		if (this.mode == jx.Widget.DatePicker.MODE_DATE_TIME) {
			if (window.innerHeight) {
				this.view.inputs.second = document.createElement("INPUT");
				this.view.inputs.second.setAttribute("type", "hidden");
			} else {
				this.view.inputs.second = document.createElement("<INPUT type='hidden'>");
			}
			this.view.container.appendChild(this.view.inputs.second);
		} else {
			this.view.container.appendChild(document.createTextNode(" "));
			if (window.innerHeight) {
				this.view.inputs.second = document.createElement("INPUT");
				this.view.inputs.second.setAttribute("type", "text");
			} else {
				this.view.inputs.second = document.createElement("<INPUT type='text'>");
			}
			this.view.inputs.second.setAttribute("size", 2);
			this.view.inputs.second.setAttribute("maxlength", 2);
			this.view.inputs.second.style.width = "2em";
			this.view.container.appendChild(this.view.inputs.second);
			this.connect(this.view.inputs.second, "onkeydown", bind(keyDownHandler, this.view.inputs.second));
		}
		this.connect(this.view.inputs.second, "onchange", bind(this.viewChanged, this));
		this.view.inputs.second.value = this.date.getSeconds();
	}
	this.viewChanged();
	return this.view.container;
};

jx.Widget.DatePicker.prototype.viewChanged = function() {
	var day = this.view.inputs.day._getSelectedValue();
	var month = this.view.inputs.month._getSelectedValue();
	var year = this.view.inputs.year._getSelectedValue();

	this.view.inputs.day._addItem(29);
	this.view.inputs.day._addItem(30);
	this.view.inputs.day._addItem(31);

	// short month
	if (month == 4 || month == 6 || month == 9 || month == 11) {
		this.view.inputs.day._removeItem(31);
	}
	// february
	if (month == 2) {
		this.view.inputs.day._removeItem(31);
		this.view.inputs.day._removeItem(30);
	}
	// leap year
	var isLeap = (year % 4) == 0;
	if (month == 2 && !isLeap) {
		this.view.inputs.day._removeItem(29);
	}

	this.view.inputs.day._selectItem(day);

	this.date.setDate(day);
	this.date.setMonth(month - 1);
	if (this.date.setFullYear) {
		this.date.setFullYear(year);
	} else {
		this.date.setYear(year);
	}

	if (this.mode == jx.Widget.DatePicker.MODE_DATE_TIME || this.mode == jx.Widget.DatePicker.MODE_DATE_TIME_SECONDS) {
		var num = parseInt(parseFloat(this.view.inputs.hour.value));
		if (isNaN(num)) num = 0;
		if (num > 23) num = 0;
		if (num < 0) num = 23;
		if (num < 10) num = "0" + num;
		this.view.inputs.hour.value = num;
		this.date.setHours(num);

		num = parseInt(parseFloat(this.view.inputs.minute.value));
		if (isNaN(num)) num = 0;
		if (num > 59) num = 0;
		if (num < 0) num = 59;
		if (num < 10) num ="0" + num;
		this.view.inputs.minute.value = num;
		this.date.setMinutes(num);

		num = parseInt(parseFloat(this.view.inputs.second.value));
		if (isNaN(num)) num = 0;
		if (num > 59) num = 0;
		if (num < 0) num = 59;
		if (num < 10) num ="0" + num;
		this.view.inputs.second.value = num;
		this.date.setSeconds(num);
	}
	this.view.field.value = this.getValue();
};

jx.Widget.DatePicker.prototype.detach = function() {
	this.supertype.detach.apply(this, arguments);
	this.view.container.parentNode.removeChild(this.view.container);
	if (this.view.field.type.toLowerCase() != "hidden") {
		this.view.field.style.display = "";
	}
};
