var Calendar = function(target)
{
	this.target = target
	this.date = new Date();
	this.listeners = []
	this.cells = []
	this.createChildren()		
}

Calendar.prototype.selected = -1
Calendar.prototype.target
Calendar.prototype.div
Calendar.prototype.grid
Calendar.prototype.cells
Calendar.prototype.date
Calendar.prototype.listeners


//
// public static methods
//
Calendar.month_names = ["January","February","March","April","May","June","July","August","September","October","November","December"];
Calendar.month_names_short = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];

//
// public methods
//
Calendar.prototype.getMonthName = function()
{
	return Calendar.month_names[this.date.getMonth()]
}
Calendar.prototype.getMonthNameShort = function()
{
	return Calendar.month_names_short[this.date.getMonth()]
}

Calendar.prototype.prev_month = function()
{
	this.date.setDate(1)
	var m = this.date.getMonth()
	if(!m){
		this.date.setMonth(11)
		this.date.setYear(this.date.getFullYear()-1)
	}else
		this.date.setMonth(m-1)
		
	this.display();
	this.dispatchEvent("onDateChanged",[this.date,"month"])

}

Calendar.prototype.next_month = function()
{
	this.date.setDate(1)
	this.date.setMonth( this.date.getMonth() + 1 )
	this.display();
	this.dispatchEvent("onDateChanged",[this.date,"month"])
}


//
// private methods
//

Calendar.prototype.createChildren = function()
{
	this.div = document.getElementById(this.target)
	this.div.className = "calendar"
	var o = document.createElement("div");
	this.grid = this.div.appendChild(o)
}

//
// return an array of days in this month with padding 
// from the previous and next month
//
Calendar.prototype.getDays = function()
{

	var days = []
	
	var d = new Date(this.date)
	d.setDate(1)
	//
	// rewind (x) number of days until we arrive on a sunday
	//
	while(d.getDay() != 0) {
		d.setDate(d.getDate() - 1)
	}
	
	//
	// find the last calendar day, include days 
	// from next month until we arrive on a saturday
	//
	var nm = new Date(this.date)
	nm.setDate(1)
	nm.setMonth(this.date.getMonth() + 1)

	while(nm.getDay() != 0) {
		nm.setDate( nm.getDate() + 1 )
	}
	
	//
	// store dates for each day and return the array
	//
	while(d.getTime() != nm.getTime())
	{
		days.push( new Date( d ) )
		d.setDate( d.getDate() + 1 )
	}
		
	return days;

}


Calendar.prototype.display = function(events)
{
	this.grid.innerHTML = "";
	this.cells = []
	
	var cal = this.getDays()
	
	for(var i=0;i<cal.length;i++)
	{
		var o = document.createElement("a");
		var d = this.grid.appendChild(o)
		d.innerHTML = cal[i].getDate()

		d.owner = this
		d.date = cal[i]
		d.href = "#"
		d.onclick = function()
		{
			//
			// return if cell is already selected
			//
			if(this.owner.selected == this)
			{
				return;
			}
			this.className = this.className_default + " selected"
			this.owner.selected.className = this.owner.selected.className_default
			this.owner.selected = this
			this.owner.date.setDate(this.date.getDate())
			this.owner.dispatchEvent("onDateChanged",[this.date,"day"])
		}

		//
		// default class for all calendar cells
		//
		d.className_default = "day"	
		d.className = d.className_default
		
		
		//
		//	special style for calendar cells outside the current month
		//
		if(cal[i].getMonth() != this.date.getMonth()) {
			d.className = d.className_default + " dead"
			d.onclick = null
		}else{
			//
			// store this cell
			//
			this.cells.push(d)
		}
		
		//
		//	select today by default
		//
		if(cal[i].getDate() == this.date.getDate() && cal[i].getMonth() == this.date.getMonth()) 
		{
			d.onclick()
		}
								
	}
		
}



//
// Event handling functions
//

Calendar.prototype.addListener = function(lo)
{
	this.listeners.push(lo)
}

Calendar.prototype.removeListener = function(lo)
{
	for(var i=0;i<this.listeners.length;i++)
	{
		if(this.listener[i] == lo)
		{
			this.listeners.splice(i,1)
			break;
		}
	}
}

Calendar.prototype.dispatchEvent = function(event,args)
{
	for(var i=0;i<this.listeners.length;i++)
	{
		var lo = this.listeners[i]
		var method = lo[event]
		if(method)
		{
			method.apply(lo,args)
		}
	}
}






