/**
 * REQUIREMENTS:
 * xy.js - Calendar constructor
 */

function leadingZero(nr)
{
	if (nr < 10) nr = "0" + nr;
	return (nr+'');
}

/**
 * DATE/TIME FUNCTIONS
 */
Date.prototype.getValidYear = function()
{
	var x = this.getYear();
	var y = x % 100;
	y += (y < 38) ? 2000 : 1900;
	return y;	
}
Date.prototype.setValidYear = function(x)
{
	var y = x % 100;
	y += (y < 38) ? 2000 : 1900;
	this.setYear(y);	
}
Date.prototype.getWeek = function()
{
	var y = this.getValidYear();
	var m = this.getMonth();
	var d = this.getDate();
	now = Date.UTC(y,m,d+1,0,0,0);
	
	var firstd = new Date();
	firstd.setYear(y);
	firstd.setMonth(0);
	firstd.setDate(1);
	
	var comp = firstd.getEurDay();
	if (comp > 3) comp -= 4;
	else comp += 3;
	
	var then = Date.UTC(firstd.getValidYear(),0,1,0,0,0);
	
	week = Math.round((((now-then)/86400000)+comp)/7);
	return (week ? week : 52);
}
Date.prototype.getEurDay = function()
{
	// converts to first-day-monday week day index
	var d = this.getDay();
	d -= 1;
	if (d == -1) d = 6;
	return d;
}

function parseDate(element, format)
{
	format = format || 'Y-m-d';
	var value = getValue(element);
	if (!value)
		return false;
	
	var sep = (format.indexOf('-') != -1
		? '-'
		: (format.indexOf('.') != -1 ? '.' : false)
	);
	if (!sep)
		return false;
	
	var digs = value.split(sep);
	var elms = format.split(sep);
	
	var date = false;
	var month = false;
	var year = false;
	for (var i=0; i<elms.length; i++) {
		switch (elms[i]) {
			case 'd':
				date = digs[i];
				break;
			case 'm':
				month = digs[i];
				break;
			case 'y':
				year = '20' + digs[i];
				break;
			case 'Y':
				year = digs[i];
				break;
		}
	}
	
	date = date*1;
	month = month*1;
	year = year*1;
	
	if (!isDate(year, month, date))
		return false;
	
	var date = new Date(year, month-1, date);
	date.setValidYear(year);
	
	return date;
}
function DaysInMonth(year, month) 
{
	if (month==4 || month==6 || month==9 || month==11) 
		return 30;
	if (month==2) 
		return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28);
	return 31;
}
function isDate(year, month, date)
{
	if (!year || !month || !date)
		return false;

	if (month<1 || month>12)
		return false;
	var days = DaysInMonth(year, month)
	if (date<1 || date>days)
		return false;
	if (year<1)
		return false;
	return true;
}

/**
 * Calendar window
 */
Calendar = function(now, className, doc, x, y)
{
	now = now || new Date();
	className = className || 'date_select';
	doc = doc || document.body;

	if (doc != document.body || x)
	{
		// you can pass obj, or x and y
		if (doc == document.body && !y) {
			obj = x;
			if (!isObject(obj))
				obj = getElement(obj);
			x = getPageX(obj);
			y = getPageY(obj);
		}
		
		this.doc = doc;
		this.abs = (doc == document.body);
		this.x = x;
		this.y = y;
		this.now = now;
		this.className = className;
		this.date = new Date(now);
		this.date.setDate(1);
		this.months = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
		this.weeks = false;
		this.days = new Array('Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su');
		this.minYear = 1938;
		this.maxYear = 2038;
		this.events = new Array();
		this.ctr = "arrows";
	}
}
Calendar.prototype.setDays = function(days_arr)
{
	this.days = days_arr;
}
Calendar.prototype.setWeeks = function(b)
{
	this.weeks = b;
}
Calendar.prototype.setMonths = function(months_arr)
{
	this.months = months_arr;
}
Calendar.prototype.setEvents = function(events_arr)
{
	this.events = events_arr;
}
Calendar.prototype.getMonth = function()
{
	return this.date.getMonth();
}
Calendar.prototype.setMonth = function(m)
{
	var y = this.date.getValidYear();
	if ((y != this.minYear || m > -1) && (y != this.maxYear || m < 12)) {
		this.date.setMonth(m);
		this.update();
	}
}
Calendar.prototype.getYear = function()
{
	return this.date.getValidYear();
}
Calendar.prototype.setYear = function(y)
{
	if (y >= this.minYear && y <= this.maxYear) {
		this.date.setValidYear(y);
		this.update();
	}
}
Calendar.prototype.setMinYear = function(y)
{
	this.minYear = y;
}
Calendar.prototype.setMaxYear = function(y)
{
	this.maxYear = y;
}
Calendar.prototype.setController = function(ctr)
{
	this.ctr = ctr;
}
Calendar.prototype.open = function()
{
	var self = this;
	
	// create bg div
	if (this.abs) {
		this.scr = document.createElement('div');
		this.scr.style.position = 'absolute';
		this.scr.style.top = '0px';
		this.scr.style.left = '0px';
		this.scr.style.width = '100%';
		this.scr.style.height = this.doc.clientHeight + "px";
		this.scr.onmouseover = function(){self.close();}
		this.doc.appendChild(this.scr);
	}
	
	// create contents div
	this.c = document.createElement('div');
	this.c.className = this.className;
	if (this.abs) {
		this.c.style.left = this.x + "px";
		this.c.style.top = this.y + "px";
	}
	this.doc.appendChild(this.c);	
	
	// toolbar
	var tb = document.createElement('div');
	tb.className = 'toolbar';
	this.c.appendChild(tb);
	
	// month div
	var m = document.createElement('div');
	m.className = 'month';
	tb.appendChild(m);
	
	// year div
	var y = document.createElement('div');
	y.className = 'year';
	tb.appendChild(y);

	// controller
	if (this.ctr == 'select')
	{
		// month select
		this.ms = document.createElement('select');
		for (var i in this.months)
			this.ms.options[this.ms.options.length] = new Option(this.months[i], i);
		this.ms.onchange = function() {
			self.setMonth(this.value);
		}
		m.appendChild(this.ms);
		
		// year select
		this.ys = document.createElement('select');
		for (var i=this.minYear; i<=this.maxYear; i++)
			this.ys.options[this.ys.options.length] = new Option(i);
		this.ys.onchange = function() {
			self.setYear(this.value);
		}
		y.appendChild(this.ys);
		
		// arrows
		var a = this.makeArrows(tb);
		a.l.onmousedown = function(){
			self.setMonth(self.getMonth()-1);
		}
		a.r.onmousedown = function(){
			self.setMonth(self.getMonth()+1);
		}
	}
	else
	{
		// month arrows
		var a = this.makeArrows(m);
		a.l.onmousedown = function(){
			self.setMonth(self.getMonth()-1);
		}
		a.r.onmousedown = function(){
			self.setMonth(self.getMonth()+1);
		}
		
		// month title
		this.mt = document.createElement('div');
		this.mt.className = 'val';
		m.appendChild(this.mt);
		
		// year arrows
		var a = this.makeArrows(y)
		a.l.onmousedown = function(){
			self.setYear(self.getYear()-1)
		}
		a.r.onmousedown = function(){
			self.setYear(self.getYear()+1);
		}
		
		// year title
		this.yt = document.createElement('div');
		this.yt.className = 'val';
		y.appendChild(this.yt);
	}
	
	// show current month
	this.update();
	
	// hide select`s IE
	if (this.abs) {
		var selects = document.getElementsByTagName('SELECT');
		for (var i=0; i<selects.length; i++)
			selects[i].style.visibility = 'hidden'
	}
}
Calendar.prototype.update = function()
{
	var self = this;
	var m = this.date.getMonth();
	var y = this.date.getValidYear();
	
	// update controller
	if (this.ctr == 'select') {
		this.ys.selectedIndex = y - this.minYear;
		this.ms.selectedIndex = m;
	}
	else {
		this.yt.innerHTML = y;
		this.mt.innerHTML = this.months[m];
	}
	
	// remove and recreate the table
	if (this.tbl !== undefined){
		this.c.removeChild(this.tbl);
		delete this.tbl;
	}
	
	this.tbl = document.createElement('table');
	this.tbl.cellSpacing = 0;
	
	this.c.appendChild(this.tbl);
	
	// header
	var h = this.tbl.insertRow(0)
	h.className = "header";
	if (this.weeks) {
		var c = h.insertCell(h.cells.length);
		c.date = new Date(this.date);
		c.className = "month_out";
		if (this.date.getValidYear() == this.now.getValidYear() && this.date.getMonth() == this.now.getMonth())
			c.className += " month_current";
		c.onmouseover = function(){this.className = this.className.replace(/out/,"over");}
		c.onmouseout = function(){this.className = this.className.replace(/over/,"out");}
		if (this.onMonth)
			c.onclick = function() { self.onMonth(this.date); }
	}
	for (var i in this.days){
		var c = h.insertCell(h.cells.length)
		c.innerHTML = this.days[i];
	}
	
	// create empty cells
	var empty_cells = this.date.getEurDay();
	if (empty_cells > 0)
	{
		var row = this.tbl.insertRow(this.tbl.rows.length)
		if (this.weeks) {
			var c = row.insertCell(row.cells.length);
			c.date = new Date(this.date);
			c.innerHTML = this.date.getWeek();
			c.className = "week_out";
			if (this.date.getValidYear() == this.now.getValidYear() && this.date.getWeek() == this.now.getWeek())
				c.className += " week_current";
			c.onmouseover = function(){this.className = this.className.replace(/out/,"over");}
			c.onmouseout = function(){this.className = this.className.replace(/over/,"out");}
			if (this.onWeek)
				c.onclick = function() { self.onWeek(this.date); }
		}
		for (i=0; i<empty_cells; i++){
			row.insertCell(row.cells.length)
		}
	}
	
	// dates
	while (m == this.date.getMonth())
	{
		// add new row
		if (this.date.getEurDay() == 0) {
			var row = this.tbl.insertRow(this.tbl.rows.length)
			if (this.weeks) {
				var c = row.insertCell(row.cells.length);
				c.date = new Date(this.date);
				c.innerHTML = this.date.getWeek();
				c.className = "week_out";
				if (this.date.getValidYear() == this.now.getValidYear() && this.date.getWeek() == this.now.getWeek())
					c.className += " week_current";
				c.onmouseover = function(){this.className = this.className.replace(/out/,"over");}
				c.onmouseout = function(){this.className = this.className.replace(/over/,"out");}
				if (this.onWeek)
					c.onclick = function() { self.onWeek(this.date); }
			}
		}
		
		// cell
		var c = row.insertCell(row.cells.length);
		c.date = new Date(this.date);
		c.innerHTML = this.date.getDate();
		c.className = "day_out";
		
		if (this.date.getMonth() == this.now.getMonth() &&
			this.date.getValidYear() == this.now.getValidYear() &&
			this.date.getDate() == this.now.getDate()
		) {
			c.className += " day_current";
		}
		
		for (var i = 0; i < this.events.length; i++)
		{
			if (this.date.getMonth() == this.events[i].getMonth() &&
				this.date.getValidYear() == this.events[i].getValidYear() &&
				this.date.getDate() == this.events[i].getDate()) {
				c.className += " event_out";
				break;
			}
		}
			
		
		c.onmouseover = function(){this.className = this.className.replace(/out/,"over");}
		c.onmouseout = function(){this.className = this.className.replace(/over/,"out");}
		if (this.onDay)
			c.onclick = function(){self.onDay(this.date);}
		
		this.date.setDate(this.date.getDate()+1)
	}
	// rewind
	this.date.setMonth(this.date.getMonth()-1);
}

Calendar.prototype.close = function()
{
	this.doc.removeChild(this.c);
		
	if (this.abs) {
		this.doc.removeChild(this.scr);
	
		// show select`s IE
		var selects = document.getElementsByTagName('SELECT');
		for (var i=0; i<selects.length; i++)
			selects[i].style.visibility = 'visible';
	}
}

Calendar.prototype.makeArrows = function(target)
{
	// arrows
	var a = document.createElement('div');
	a.className = 'arrows';
	target.appendChild(a);
	// left
	var l = document.createElement('a');
	l.className = 'left';
	l.href = 'javascript:;';
	a.appendChild(l);
	// right
	var r = document.createElement('a');
	r.className = 'right';
	r.href = 'javascript:;';
	a.appendChild(r);
	
	return {'l':l, 'r':r}
}
