/*
 * Javascript Calendar
 *
 * @author Paul Hameteman <paul@appsoluut.com>
 * @copyright Copyright (c) 2008, AppSoluut
 * @link http://appsoluut.com
 * @version $Id
 * @package Calendar
 */


/*
 * Constructor of Calendar object
 *
 * Initialize values and draw the calendar
 * @param string name Name of (hidden) text field
 * @param int month Month of the year | 1 .. 12
 * @param int year Year | 1970 .. 20xx
 */
function Calendar(name, year, month)
{
	/* Variables */
	this.name				= name;
	this.month				= month;
	this.year				= year;
	this.firstDay			= 0;
	this.mindate			= 0;
	this.mindate_day		= 0;
	this.maxdate			= 0;
	
	this.at_mindate			= false;
	this.at_maxdate			= false;
	this.selectableDays		= new Array(1, 2, 3, 4, 5, 6, 7);
	
	this.selectedDays		= new Array();

    this.dayNames			= new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
    this.dayNamesLong		= new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
    this.monthNames			= new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
    this.callback			= '';

    var d = new Date();
    if(typeof(month) == 'undefined')
    	this.month = d.getMonth() + 1;

    if(typeof(year) == 'undefined')
    	this.year = d.getYear();

	/* Functions */
	this.draw				= Calendar.draw;
	this.setMinDate			= Calendar.setMinDate;
	this.setMaxDate			= Calendar.setMaxDate;
	this.setMonth			= Calendar.setMonth;
	this.setFirstDay		= Calendar.setFirstDay;
	this.setDayNames		= Calendar.setDayNames;
	this.setDayNamesLong	= Calendar.setDayNamesLong;
	this.setMonthNames		= Calendar.setMonthNames;
	this.setSelectableDays	= Calendar.setSelectableDays;
	this.getWeekday			= Calendar.getWeekday;
	
	this.selectDay			= Calendar.selectDay;
	this.deselectDay		= Calendar.deselectDay;
	this.emptyDay			= Calendar.emptyDay;
	this.getSelectedDays	= Calendar.getSelectedDays;
	this.registerCallback	= Calendar.registerCallback;
	this.getNext			= Calendar.getNext;
	this.getString			= Calendar.getString;
	
	this.monthName			= Calendar.monthName;
	this.monthLength		= Calendar.monthLength;
}

Calendar.selectDay = function(date, enableCallback)
{
	var date_array = date.split('-');
	var year	= parseInt(date_array[0], 10);
	var month	= parseInt(date_array[1], 10);
	var day		= parseInt(date_array[2], 10);
	
	/*
	if(month < 10) month = '0' + month;
	if(day < 10) day = '0' + day;
	*/

	// Make it a valid date for this calendar
	this.selectedDays.push(year + '-' + month + '-' + day);

	if(enableCallback && this.callback)
	{
		this.callback();
	}
	this.draw();
}

Calendar.deselectDay = function(date)
{
	var temp = new Array();
	for(i in this.selectedDays)
	{
		if(this.selectedDays[i] != date)
			temp.push(this.selectedDays[i]);
	}
	
	this.selectedDays = temp;
}

Calendar.emptyDay = function()
{
	this.selectedDays = new Array();
}

Calendar.registerCallback = function(functionName)
{
	this.callback = functionName;
}

Calendar.getSelectedDays = function()
{
	return this.selectedDays;
}

Calendar.setSelectableDays = function(days)
{
	this.selectableDays = days;
}

Calendar.setMinDate = function(year, month, day, hour, min, sec)
{
	var date;
	if(year == 'now')
		date = new Date();
	else
		date = new Date(year, --month, day, hour, min, sec);
		
	this.mindate = date;
	this.mindate_day = date.getDate();
}

Calendar.setMaxDate = function(year, month, day, hour, min, sec)
{
	var date;
	if(year == 'now')
		date = new Date();
	else
		date = new Date(year, --month, day, hour, min, sec);
		
	this.maxdate = date;
}

Calendar.getWeekday = function(date)
{
	var date_array = date.split('-');
	var year	= parseInt(date_array[0], 10);
	var month	= parseInt(date_array[1], 10);
	var day		= parseInt(date_array[2], 10);
	
	var d = new Date(year, month-1, day, 0, 0, 0);
	return d.getDay();
}

Calendar.setMonth = function(month)
{
	if(month)
	{
		if(typeof(month) == 'number' && (month >= 0 && month <= 12))
		{
			this.month = month;
		}
		else if(month == 'today')
		{
			this.year = Today.Year;
			this.month = Today.getMonth();
		}
		else if(month == 'prev')
		{
			if(--this.month == 0)
			{
				this.month = 12;
				--this.year;
			}
		}
		else if(month == 'next')
		{
			if(++this.month > 12)
			{
				this.month = 1;
				++this.year;
			}
		}
		else if(month != 'now')
			alert('Unknown month: ' + month);
		
		if(this.mindate)
		{
			if(this.year <= this.mindate.getYear() && this.month - 1 < this.mindate.getMonth())
			{
				this.year = this.mindate.getYear();
				this.month = this.mindate.getMonth();
				this.month++;
				this.at_mindate = true;
			}
			else
				this.at_mindate = false;
		}

		if(this.maxdate)
		{
			if(this.year >= this.maxdate.getYear() && this.month - 1 > this.maxdate.getMonth())
			{
				this.year = this.maxdate.getYear();
				this.month = this.maxdate.getMonth();
				this.month++;
				this.at_maxdate = true;
			}
			else
				this.at_maxdate = false;
		}
	}

	this.ThisDate = (this.month == Today.getMonth() && this.year == Today.Year)?  Today.getDate() : 0;
}

/*
 * Change first weekday
 *
 * @param int firstDay Starting day of the week | 0 .. 6
 */
Calendar.setFirstDay = function(firstDay)
{
	this.firstDay = firstDay;
}


/*
 * Set month names
 */
Calendar.setMonthNames = function()
{
	var args = Calendar.setMonthNames.arguments;
	for(var i = 0; i < args.length; i++)
		this.monthNames[i] = args[i];      
}


/*
 * Set day names
 */
Calendar.setDayNames = function()
{
	var args = Calendar.setDayNames.arguments;
	for(var i = 0; i < args.length; i++)
		this.dayNames[i] = args[i];
}


/*
 * Set long day names
 */
Calendar.setDayNamesLong = function()
{
	var args = Calendar.setDayNamesLong.arguments;
	for(var i = 0; i < args.length; i++)
		this.dayNamesLong[i] = args[i];
}


/*
 * Return name of the month
 * @returns string Name of the month
 */
Calendar.monthName = function()
{
	return this.monthNames[this.month - 1];
}


/*
 * Get days in month
 */
Calendar.monthLength = function(year, month)
{
	var m = this.month;
	var y = this.year;

	if(month > 0)
		m = month;
	if(year > 0)
		y = year;
		
    var len = ((m % 7) % 2 == 0) ? 30 : 31;

	/* July has 31 days */
	if(m == 7)
		len = 31;

    /* Check leap-year for February */
    if(m == 2)
    	len = (y % 4 == 0) ? 29 : 28;

    return len;
}

Calendar.getNext = function(date, days)
{
	var date_array = date.split('-');
	var year	= parseInt(date_array[0], 10);
	var month	= parseInt(date_array[1], 10);
	var day		= parseInt(date_array[2], 10);

	var one_day	= 1000 * 60 * 60 * 24;
	
	var end_date = new Date(year, month - 1, day + days);

	var end_year	= end_date.getYear();
	var end_month	= end_date.getMonth() + 1;
	var end_day		= end_date.getDate();

	return end_year + '-' + end_month + '-' + end_day;
}

Calendar.getString = function(date)
{
	var date_array = date.split('-');
	var year	= parseInt(date_array[0], 10);
	var month	= parseInt(date_array[1], 10);
	var day		= parseInt(date_array[2], 10);

	var d		= new Date(year, month - 1, day);	
	
	return this.dayNamesLong[d.getDay()] + ' ' + day + ' ' + this.monthNames[month-1] + ' ' + year;
}

/*
 * Draw calendar
 *
 * @param int year Year | 1970 .. 20xx
 * @param int month Month of the year | 1 .. 12
 */
Calendar.draw = function(year, month)
{
	var str = '<table border="0" cellspacing="0" cellpadding="0">';
	o = document.getElementById(this.name);
	
	if(o)
	{
		var first		= new Date(this.year, this.month-1, 1);
		var lastDate	= this.monthLength();
		var day			= 0;
		
		if(this.mindate)
		{
			if(this.year == this.mindate.getYear() && this.month - 1 == this.mindate.getMonth())
				this.at_mindate = true;
			else
				this.at_mindate = false;
		}

		if(this.maxdate)
		{
			if(this.year == this.maxdate.getYear() && this.month - 1 == this.maxdate.getMonth())
				this.at_maxdate = true;
			else
				this.at_maxdate = false;
		}

		str += '<tr class="head"><th>';
		if(!this.at_mindate)
			str += '<a href="javascript:this.setMonth(\'prev\')">&lt;&lt;</a>';
		str += '</th><th colspan="5">' + this.monthName() + ' ' + this.year + '</th><th>';
		if(!this.at_maxdate)
			str += '<a href="javascript:this.setMonth(\'next\')">&gt;&gt;</a>';
		str += '</th></tr>';
	
		str += '<tr align="center">\n';
		for(day = this.firstDay; day < this.firstDay + 7; day++)
			str += '<td>' + this.dayNames[day % 7] + '</td>';
	
		day = first.getDay();
	    if (day != this.firstDay)
	    {
			str += '</tr>\n<tr align="center">\n';
			str += '<td colspan=' + ((day + 7 - this.firstDay) % 7) + '>&nbsp;</td>\n';
	    }
	
		for(date=1; date <= lastDate; date++)
		{
			if(++day == 8)
				day = 1;
			
	        if(day == this.firstDay % 7 + 1)
	            str += '</tr>\n<tr align="center">\n';
	
			show_link = false;
			for(i in this.selectableDays)
			{
				if(this.selectableDays[i] == day)
					show_link = true;
			}
			
			if(show_link && this.at_mindate && date <= this.mindate_day)
				show_link = false;
	
			var onclick = '';
			if(show_link)
				onclick = 'onclick="' + this.name + '.selectDay(\'' + this.year + '-' + this.month + '-' + date + '\', 1)"';
			
			// check if date is selected
			var date_selected = false;
			for(i in this.selectedDays)
			{
				if(this.year + '-' + this.month + '-' + date == this.selectedDays[i])
				{
					date_selected = true;
					break;
				}
			}
			
			if(date_selected)
				str += '<td ' + onclick + ' class="selected" nowrap="nowrap">';
			else if(day == 1 || day == 7)
				str += '<td ' + onclick + ' class="weekend" nowrap="nowrap">';
			else
				str += '<td ' + onclick + ' class="workday" nowrap="nowrap">';
				
			if(show_link)
				str += '<a href="javascript://">';
				
			str += date;
			
			if(show_link)
				str += '</a>';
			
			str += '</td>';
		}

	    if (day != this.firstDay)
	        str += '<td colspan=' + ((day + 7 - this.firstDay) % 7) + '>&nbsp;</td>\n';

		str += '</tr></table>';
	
		o.innerHTML = str;
	}
}

if(!Today)
	var Today = new Date();

if(!Today.Year)
{
	Today.Year = Today.getYear();
	if(navigator.appName.indexOf('Netscape') != -1 || (Today.Year < 100 && Today.Year >= 0)) 
		Today.Year += 1900;
}
