// JavaScript Document
var month_names = ["jan", "feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"];
var month_names_display = ["January", "February","March","April","May","June","July","August","September","October","November","December"];
var day_names = ['mo','tu','we','th','fr','sa','su'];
var day_names_display = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
var day_classes = ['su','mo','tu','we','th','fr','sa'];

/* sugar method - makes an element */
function make(element, className) {
	var e = document.createElement(element);
	e.className = className;
	return e;
}

function Page(date, cal) {
	this.prev = null;
	this.next = null;
	this.node = null;	
	this.year = date.getFullYear();
	this.month = date.getMonth();
	this.cal = cal;
}

Page.prototype.getMonthName = function() {
	return month_names[this.month];
}

Page.prototype.getNode = function() {
	return this.node = this.node || this.initNode();
}

Page.prototype.getPreviousPage = function() {
	if (!this.prev) {
		var prevMonth = new Date(this.year, this.month -1);
		this.prev = new Page(prevMonth, this.cal);
		this.prev.next = this; //two way link
	}	
	return this.prev;
}

Page.prototype.getNextPage = function() {
	if (!this.next) {
		var nextMonth = new Date(this.year, this.month + 1);
		this.next = new Page(nextMonth, this.cal);
		this.next.prev = this; //two way link
	}
	return this.next;
}

Page.prototype.initNode = function() {
	var node = make('div', 'page');
	
	var h = node.appendChild(make('div'));	
	
	h.appendChild(make('span', 'head_month')).innerHTML = this.getMonthName();
	h.appendChild(make('span', 'head_year')).innerHTML = this.year;	
	
	node.appendChild(this.createDayTable());

	return node;
}

Page.prototype.selectDate = function(time) {
	this.cal.onDateSelect(time);
}

/*
Creates a table of the days for this page
*/
Page.prototype.createDayTable = function() {
	var d = this.datePreviousMonday();
	var endTime = this.dateFollowingSunday().getTime();
	var table = make('table', 'grid');
	table.cellPadding = 0;
	table.cellSpacing = 0;
	
	var th = table.createTHead().insertRow(0);
	for (var i = 0; i < day_names.length; i++) {
		var cell = th.insertCell(i);
		cell.innerHTML = day_names[i];
	}
	var tbody = table.appendChild(document.createElement('tbody'));
	while (d.getTime() <= endTime) {
		var w = tbody.insertRow(-1);
		
		for (var j = 0; j < 7; j++) {
			var day = w.insertCell(j);
			day.appendChild(document.createTextNode(d.getDate()));
			day.time = d.getTime();
			day.page = this;
			day.onclick = function(e) { this.page.selectDate(this.time); }
			day.onmouseover = function(e) { 
				this.prevClassName = this.className;
				this.className += ' over';
			}
			day.onmouseout = function(e) {
				this.className = this.prevClassName;	
			}
			
			day.className = this.getDayClassName(d);
			
			d.setDate(d.getDate() + 1); //increment
		}	
	}
	
	return table;
}


/* get a suitable class for the given date */
var _now_ = new Date();
var _today_ = new Date(_now_.getFullYear(), _now_.getMonth(), _now_.getDate());

Page.prototype.getDayClassName = function(date) {
	var className = 'day';	
	
	if (date.getMonth() == this.month) {					
		className += ' ' + day_classes[date.getDay()];
	
		if (date.getTime() == _today_.getTime()) 
			className += ' today';
	}
	else {
		className += " edge_month";		
	}
		
	if (date.getTime() < _today_.getTime())
		className += ' past';
		
	return className;
}


/*
Returns the date of the monday on or before the first day of the month.
*/
Page.prototype.datePreviousMonday = function() {
	var m = new Date(this.year, this.month, 1);
	
	while (m.getDay() != 1) 
		m.setDate(m.getDate() -1);	

	return m;
}
						
/*
Returns the date of the sunday on or after the last day of the month
*/						
Page.prototype.dateFollowingSunday = function() {
	var s = new Date(this.year, this.month + 1, 0); //0th day of next month means last day of this month
	
	while (s.getDay() != 0)
		s.setDate(s.getDate() + 1);
		
	return s;
}

/*
	var params = {
		date:new Date(),
		container_id:'',
		input_id:'',
		display_id:'',
		click_id:'',
		num_months:1,
		can_select_past:true
	}
*/
function Calendar(params)
{
	this.container = document.getElementById(params.container_id);
	this.inputElement = document.getElementById(params.input_id);
	this.displayElement = document.getElementById(params.display_id);
	this.clickElement = document.getElementById(params.click_id);
	this.canSelectPast = params.can_select_past;
	if (params.click_function) { this.clickFunction = params.click_function; }
	this.isPopup=params.popup;
	
	numPages = params.num_months;
	date = params.date;
	
	this.node = make('div', 'calendar');
	
	var bar = this.node.appendChild(make('div', 'buttonbar'));
	var p = bar.appendChild( make('a', 'button') );
	p.innerHTML = '&laquo;';
	p.cal = this;
	p.onmousedown = function(e) { this.cal.showprevious(); return false; }

	var n = bar.appendChild( make('a', 'button') );
	n.innerHTML = '&raquo;';
	n.cal = this;
	n.onmousedown = function(e) { this.cal.shownext(); return false; }	
	
	var c = this.node.appendChild( make ('a','button close'));
	c.innerHTML = '&chi;';
	c.container = this.container;
	c.onclick = function(e) { this.container.style.display = 'none'; }
	
	if (!numPages || numPages < 1) {
		numPages = 1;
	}
	
	this.pages = [];
	var page = new Page(date, this);
	for (var i=0; i < numPages; i++, page = page.getNextPage()) {
		this.node.appendChild( page.getNode() );
		this.pages.push(page);
	}
	if (this.isPopup!==false)
	{
	this.container.style.display = 'none';
	this.displayElement.container = this.container;
	this.displayElement.onclick = function(e) {
		this.container.style.display = 'inline';
	}	
	this.clickElement.container = this.container;
	this.clickElement.onclick = function(e) {
		this.container.style.display = 'inline';
	}	
}
}






Calendar.prototype.onDateSelect = function(time) {
	var d = new Date(time);
	var isFuture = d.getTime() >= _today_.getTime();
	if (isFuture || this.canSelectPast) {
		this.displayElement.innerHTML = day_names_display[d.getDay()] + ' ' + d.getDate() + ' ' + month_names_display[d.getMonth()] + ', ' + d.getFullYear();
		this.inputElement.value = d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate();
		if (this.isPopup!==false)
		{
		this.container.style.display = 'none';
		}
		if (this.clickFunction)
		{
			this.clickFunction(d);
		}
	}
}

Calendar.prototype.shownext = function() {
	var nextPage = this.pages[this.pages.length - 1].getNextPage()
	this.pages.push( nextPage );
	this.node.appendChild( nextPage.getNode() );
	this.node.removeChild( this.pages.shift().getNode() );	   
}

Calendar.prototype.showprevious = function() {
	var firstPage = this.pages[0];
	var prevPage = firstPage.getPreviousPage();
	this.pages.unshift( prevPage );
	this.node.insertBefore( prevPage.getNode(), firstPage.getNode() );
	this.node.removeChild( this.pages.pop().getNode() );
}	

Calendar.prototype.getNode = function() {
	return this.node;
}

Calendar.prototype.setDisplayElement = function(id) {
	var e = document.getElementById(id);
	this.displayElement = e;
}

Calendar.prototype.setInputElement = function(id) {
	var e = document.getElementById(id);
	this.inputElement = e;
}

Calendar.prototype.show = function() {
	this.container.innerHTML = "";
	this.container.appendChild(this.getNode());
}
