/**
 *	Reisplanner Calendar
 *	-------------------------------
 */

function Calendar(node, settings) {
	this.container = node;
	this.table = node.getElementsByTagName('table')[0];
	this.body = node.getElementsByTagName('tbody')[0];
	this.currentCell = null;
	this.allowPast = settings.allowPast;
	
	var selects = node.getElementsByTagName("select");
	
	EventListener.addEvent(this.table, 'mouseup', this.scope(this.getDate));
	EventListener.addEvent(this.table, 'mousemove', this.scope(this.hoverDate));
	EventListener.addEvents(selects, 'change', this.scope(this.upDate));

	var now = new Date();
	this.now = new Date(now.getFullYear(), now.getMonth(), now.getDate());

	this.chooseDate(selects[0]);
}

Calendar.prototype = {
	upDate:function(e) {
		var target = EventListener.getTarget(e, 'select');
		if(target) {
			this.chooseDate(target);
		}
	},

	chooseDate:function(target) {
		if(/year|month/i.test(target.className)) {
			var selects = target.parentNode.getElementsByTagName("select");
			var year = parseInt(selects[0].value, 10);
			var month = parseInt(selects[1].value, 10) -1;
		} else {
			var date = target.value.split('index.html');
			var year = parseInt(date[0], 10);
			var month = parseInt(date[1] || 1, 10) -1;
		}

		this.setDate(new Date(year, month, 1));
	},

	setSelects:function() {
		function selectValue(select, value) {
			for (var i=0; i<select.options.length; i++) {
				if(select.options[i].value == value) {
					select.selectedIndex = i;
					break;
				}
			}
		}

		var date = this.selectedDate;
		var selects = this.container.getElementsByTagName("select");
		if(this.allowPast) {
			selectValue(selects[0], date.getFullYear());
			selectValue(selects[1], date.getMonth()+1);
		} else {
			var s = date.getFullYear() + '/' + /[0-9]{2}$/.exec('0'+ (date.getMonth()+1))[0] + '/01';
			selectValue(selects[0], s);
		}
	},

	setDate:function(date) {
		this.currentDate = date;
		this.currentMonth = date.getMonth();
		this.currentYear = date.getFullYear();
		this.selectedDate = new Date(date.getTime());
		this.setSelects();
		this.createTable();
	},

	setAction:function(action) {
		this.action = action;
	},

	hoverDate:function(e) {
		var target = EventListener.getTarget(e);
		var day = target.innerHTML;
		if(this.currentCell && (!target || target != this.currentCell))
			ClassName.remove(this.currentCell, 'current');
		
		if(/td/i.test(target.nodeName) && /^[0-9]+$/.test(day) && !/past/.test(target.className)) {
			this.currentCell = target
			ClassName.add(target, 'current');
		}
	},

	getDate:function(e){
		var target = EventListener.getTarget(e);
		var day = target.innerHTML;
		
		if(/td/i.test(target.nodeName) && /^[0-9]+$/.test(day) && !/past/.test(target.className)) {
			try {
				this.action(new Date(this.currentYear, this.currentMonth, day));
			} catch (actionException) {
				alert('Error. No calendar action specified.');
			}
		}
	},

	createTable:function() {
		var date = this.currentDate;
		
		date.setDate(1);		
		var day, row, cell, endmode = false;
		var month = date.getMonth();
		var first = date.getDay();
		var days = first + 42;
		var body = document.createElement('tbody');
		
		this.currentCell = null;
		this.table.removeChild(this.body);
		this.body = this.table.appendChild(body);

		for(var i=0; i<days; i++) {
			day = i+1 - first;
			date.setMonth(month);
			
			if(day < 1) day = ' ';
			else {
				date.setDate(day);
				if(date.getMonth() != month) {
					day = ' ', endmode = true;
				}
			}

			if(i%7 == 0) {
				if(endmode) break;
				row = this.body.insertRow(i/7);
			}	
			
			cell = row.insertCell(i%7)
			cell.innerHTML = day;
			if(date < this.now && !this.allowPast) {
				cell.className = 'past';
			}

			if(day > 1 && Math.abs(this.selectedDate - date) < 86400000) {
				cell.className += ' today';
			}

			if(i%7 == 0 || i%7 == 6) {
				cell.className += ' weekend';
			}
		}
	},

	shiftDate:function(dy, dm){
		var mm = this.currentMonth += dm;
		var yy = this.currentYear += dy;

		if(mm%12 < 0 || mm > 12) {
			yy += mm%12;
			mm = (12 + mm)%12;
		}

		this.currentDate = new Date(yy, mm, 1)
		this.currentMonth = mm;
		this.currentYear = yy;
		this.createTable();
	},

	scope:function(method) {
		var scope = this;
		return function() {
			return method.apply(scope, arguments);
		}
	}
}