/**
 * Calendar
 *
 * @author Kazuyuki Nishijima (http://www.meibinlab.jp/)
 */
var Calendar = Class.create();
Calendar.prototype = {

	version: "00.01.04",
	
	element: null,

	dialog: null,
	
	appended: false,
	
	valueDate: null,
	
	currentYear: null,
	
	currentMonth: null,
	
	initialize: function(options) {
		options = (options == null) ? Array() : options;
		options["unit"] = (options["unit"] == null) ? "em" : options["unit"];
		options["delay"] = (options["delay"] == null) ? 100 : options["delay"];
		this.options = options;
		
		this._initializeDialog();
	},
	
	show: function(id, left, top) {
		if (this.appended == false) {
			document.body.appendChild(this.dialog);
			this.appended = true;
		}
		
		this.element = $(id);
		if (left == null) {
			left = 0;
			var target = this.element;
			while (target) {
				left += target.offsetLeft;
				target = target.offsetParent;
			}
			this.dialog.style.left = left + "px";
		} else {
			this.dialog.style.left = left + this.options["unit"];
		}
		
		if (top == null) {
			top = 0;
			var target = this.element;
			while (target) {
				top += target.offsetTop;
				target = target.offsetParent;
			}
			top += this.element.offsetHeight;
			this.dialog.style.top = top + "px";
		} else {
			this.dialog.style.top = top + this.options["unit"];
		}
		
		this.valueDate = new Date(this.element.value);
		if (!this.valueDate.getTime()) {
			this.valueDate = new Date();
		}
		
		this.currentYear = this.valueDate.getFullYear();
		this.currentMonth = this.valueDate.getMonth();
		this._changeMonth(null, 0, 0);
		
		setTimeout(this._show.bind(this), this.options["delay"]);
	},
	
	hide: function() {
		if (this.dialog.style.display == "none") {
			return;
		}
		setTimeout(this._hide.bind(this), this.options["delay"]);
	},
	
	_initializeDialog: function() {
		this.dialog = document.createElement("div");
		this.dialog.style.display = "none";
		this.dialog.style.position = "absolute";
		this.dialog.style.left = "0px";
		this.dialog.style.top = "0px";
		Element.addClassName(this.dialog, "Calendar_dialog");
		
		innerHtml = "<table>";
		innerHtml += "<tr>";
		innerHtml += "<td colspan='4' class='Calendar_year'><button title='previous'>&lt;</button><span class='Calendar_year_label'></span><button title='next'>&gt;</button></td>";
		innerHtml += "<td colspan='2' class='Calendar_month'><button title='previous'>&lt;</button><span class='Calendar_month_label'></span><button title='next'>&gt;</button></td>";
		innerHtml += "<td class='Calendar_close'><button title='close'>X</button></td>";
		innerHtml += "</tr>";
		for (ii = 0; ii < 6; ii++) {
			innerHtml += "<tr class='Calendar_week'>";
			for (jj = 0; jj < 7; jj++) {
				innerHtml += "<td class='Calendar_day'>&nbsp;</td>";
			}
			innerHtml += "</tr>";
		}
		innerHtml += "<table>";
		this.dialog.innerHTML = innerHtml;
		
		var tds = this.dialog.getElementsByTagName("td");
		
		var yearButtons = tds[0].getElementsByTagName("button");
		var prevYearButton = yearButtons[0];
		prevYearButton.style.textAlign = "center";
		prevYearButton.style.cursor = "pointer";
		Event.observe(prevYearButton, 'click', this._changeMonth.bindAsEventListener(this, -1, 0));

		var nextYearButton = yearButtons[1];
		Event.observe(nextYearButton, 'click', this._changeMonth.bindAsEventListener(this, 1, 0));
		
		var monthButtons = tds[1].getElementsByTagName("button");
		var prevMonthButton = monthButtons[0];
		Event.observe(prevMonthButton, 'click', this._changeMonth.bindAsEventListener(this, 0, -1));
		
		var nextMonthButton = monthButtons[1];
		Event.observe(nextMonthButton, 'click', this._changeMonth.bindAsEventListener(this, 0, 1));

		var closeButton = tds[2].getElementsByTagName("button")[0];
		Event.observe(closeButton, 'click', this.hide.bindAsEventListener(this));
		
		for (ii = 0; ii < 6; ii++) {
			for (jj = 0; jj < 7; jj++) {
				var offset = ii * 7 + jj;
				var dayButton = tds[offset + 3];
				dayButton.style.cursor = "pointer";
				Event.observe(dayButton, 'click', this._selectDay.bindAsEventListener(this, offset));
			}
		}
	},
	
	_changeMonth: function(event, moveYear, moveMonth) {
		var currentDate = new Date();
		currentDate.setDate(1);
		currentDate.setFullYear(this.currentYear + moveYear);
		currentDate.setMonth(this.currentMonth + moveMonth);
		
		this.currentYear = currentDate.getFullYear();
		this.currentMonth = currentDate.getMonth();
		
		var tds = this.dialog.getElementsByTagName("td");
		
		var yearArea = tds[0].getElementsByTagName("span")[0];
		yearArea.innerHTML = this.currentYear;
		
		var monthArea = tds[1].getElementsByTagName("span")[0];
		var month = this.currentMonth + 1;
		if (month < 10) {
			month = "&nbsp;" + month;
		}
		monthArea.innerHTML = month;
		
		currentDate.setDate(currentDate.getDate() - currentDate.getDay());

		var tmpDisplay = this.dialog.style.display;
		this.dialog.style.display = "none";

		for (ii = 0; ii < 6; ii++) {
			for (jj = 0; jj < 7; jj++) {
				var dayButton = tds[ii * 7 + jj + 3];
				dayButton.innerHTML = currentDate.getDate();
				
				var styleClass = "Calendar_day ";
				styleClass += "Calendar_day_" + currentDate.getDay() + " ";
				if (currentDate.getFullYear() < this.currentYear) {
					styleClass += "Calendar_day_prevMonth ";
				} else if (currentDate.getFullYear() == this.currentYear) {
					if (currentDate.getMonth() < this.currentMonth) {
						styleClass += "Calendar_day_prevMonth ";
					} else if (currentDate.getMonth() == this.currentMonth) {
						styleClass += "Calendar_day_currentMonth ";
					} else {
						styleClass += "Calendar_day_nextMonth ";
					}
				} else {
					styleClass += "Calendar_day_nextMonth ";
				}
				if (this.valueDate.getFullYear() == currentDate.getFullYear()
						&& this.valueDate.getMonth() == currentDate.getMonth()
						&& this.valueDate.getDate() == currentDate.getDate()) {
					styleClass += "Calendar_day_currentDay ";
				}
				dayButton.setAttribute("class", styleClass);
				dayButton.setAttribute("className", styleClass);
				
				currentDate.setDate(currentDate.getDate() + 1);
			}
		}

		this.dialog.style.display = tmpDisplay;

		return false;
	},
	
	_selectDay: function(event, offset) {
		var currentDate = new Date(this.currentYear + "/" + (this.currentMonth + 1) + "/1");
		currentDate.setDate(currentDate.getDate() - currentDate.getDay() + offset);
		
		this.element.value = currentDate.getFullYear() + "/" + (currentDate.getMonth() + 1) + "/" + currentDate.getDate();
		if (this.element.onchange) {
			this.element.onchange(event);
		}
		
		this.valueDate = currentDate;
		this._changeMonth(null, 0, 0);
		
		return false;
	},
	
	_show: function() {
		this.dialog.style.display = "block";
	},
	
	_hide: function() {
		this.dialog.style.display = "none";
	}
	
}
