/* DatePicker - Dynamic Calendar/Date Chooser Control */

function CreateDatePicker(id, isStart, monthNames, callbackFunc)
{
	var now;
	var years;
	var i;
	var calendar;
	
	/* Properties */
	calendar = document.getElementById(id + "_calendar");
	calendar._monthSelect = calendar.getElementsByTagName("select")[0];
	calendar._yearSelect = calendar.getElementsByTagName("select")[1];
	calendar._headerCells = calendar.getElementsByTagName("th");
	calendar._dayCells = calendar.getElementsByTagName("td");
	calendar._selectedIndex = 0;
	calendar._callbackFunc = callbackFunc;
	calendar._callbackArgs = id;
	
	calendar._startLimit = initDate(document.getElementById(id + "_mindate").value);
	calendar._endLimit = initDate(document.getElementById(id + "_maxdate").value);
	
	if(isStart)
	{
	    calendar._currentDate = new Date(calendar._endLimit.getTime());
	    calendar._currentDate.setDate(calendar._currentDate.getDate() - (parseInt(document.getElementById(id + "_startrange").value,10) - 1));
	    calendar._selectedDate = new Date(calendar._currentDate.getTime());
	    
	}else{
	    calendar._currentDate = new Date(calendar._endLimit.getTime());
	    calendar._selectedDate = new Date(calendar._currentDate.getTime());
	}
	//calendar._months = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
	calendar._months = monthNames;

	/* Methods */
	calendar._goBackMonth = function()
	{
		this._currentDate.setMonth(this._currentDate.getMonth() - 1);
		if((this._currentDate.getTime() < this._startLimit.getTime()) &&
			(this._currentDate.getMonth() != this._startLimit.getMonth()))
		{
			this._currentDate.setMonth(this._currentDate.getMonth() + 1);
			return;
		}
		this._update();
	};
	
	calendar._goForwardMonth = function()
	{
		this._currentDate.setMonth(this._currentDate.getMonth() + 1);
		if((this._currentDate.getTime() > this._endLimit.getTime()) &&
			(this._currentDate.getMonth() != this._endLimit.getMonth()))
		{
			this._currentDate.setMonth(this._currentDate.getMonth() - 1);
			return;
		}
		this._update();
	};
	
	calendar._update = function()
	{
		var weekday;
		var previousMonth;
		var days;
		var now;
		var i;
		
		weekday = this._getFirstDayIndex();
		previousMonth = (this._currentDate.getMonth() != 0) ? 
			this._currentDate.getMonth() - 1 : 11;

		/* Write out days from previous month */
		days = this._daysInMonth(previousMonth, this._currentDate.getFullYear());
		for(i = 0; i < weekday; i++)
		{
			this._replaceCellText(this._dayCells[i], ((days - weekday) + i) + 1);
			this._dayCells[i].className = "othermonth";
		}

		/* Write out days for current month */
		days = this._daysInMonth(this._currentDate.getMonth(), 
			this._currentDate.getFullYear());
		for(i = 0; i < days; i++)
		{
			this._replaceCellText(this._dayCells[i + weekday], (i + 1));
			if((((i + weekday) % 7) == 0) || ((((i + weekday) + 1) % 7) == 0))
				this._dayCells[i + weekday].className = "weekend";
			else
				this._dayCells[i + weekday].className = "weekday";
		}
		
		/* Write out days for next month */
		days = 42 - (weekday + days);
		for(i = 0; i < days; i++)
		{
			this._replaceCellText(this._dayCells[(42 - days) + i], (i + 1));
			this._dayCells[(42 - days) + i].className = "othermonth";
		}
		
		/* Disable any days if we're past our limit */
		now = new Date();
		now.setFullYear(this._currentDate.getFullYear());
		now.setMonth(this._currentDate.getMonth());
		now.setDate(1);
		now.setHours(0);
		now.setMinutes(0);
		now.setSeconds(0);
		now.setMilliseconds(0);
		now.setDate(now.getDate() - weekday);
		for(i = 0; i < 42; i++)
		{
			if((now.getTime() < this._startLimit.getTime()) ||
				(now.getTime() > this._endLimit.getTime()))
				AddClass(this._dayCells[i], "disabled");
			else
				RemoveClass(this._dayCells[i], "disabled");
				
			now.setDate(now.getDate() + 1);
		}
		
		/* Is the selected date on this calendar? */
		if((this._selectedDate.getFullYear() == this._currentDate.getFullYear()) &&
			(this._selectedDate.getMonth() == this._currentDate.getMonth()))
			AddClass(this._dayCells[this._selectedIndex], "selected");
		
		/* Set the drop down lists */
		this._monthSelect.selectedIndex = this._currentDate.getMonth();
		this._yearSelect.selectedIndex = 
			this._currentDate.getFullYear() - this._startLimit.getFullYear();
	};

	calendar._setDateSelection = function(index, callback, callbackArgs) {
	    if (CheckClass(this._dayCells[index], "othermonth") ||
			(CheckClass(this._dayCells[index], "disabled")))
	        return;

	    RemoveClass(this._dayCells[this._selectedIndex], "selected");
	    AddClass(this._dayCells[index], "selected");

	    this._selectedIndex = index;

	    // If the selected day does not exist in month being set, it will go to the next month
	    // If the current day is 31 and the new month only has 30, the date will adjust itself
	    // to the first of the next month
        if (this._selectedDate.getDate() > 28) this._selectedDate.setDate(1);
	    this._selectedDate.setFullYear(this._currentDate.getFullYear());
	    this._selectedDate.setMonth(this._currentDate.getMonth());
	    this._selectedDate.setDate(this._dayCells[index].firstChild.nodeValue);

	    /* Send it back */
	    if (callback) callback(callbackArgs);
	};
	
	calendar._getFirstDayIndex = function()
	{
		var now;
		var weekday;
		
		now = new Date();
		now.setFullYear(this._currentDate.getFullYear());
		now.setMonth(this._currentDate.getMonth());
		now.setDate(1);
		
		weekday = now.getDay();
		if(weekday == 0)
			weekday = 7;
		
		return weekday;
	};

	calendar._daysInMonth = function(month, year)
	{
		var days;
		
		if((month == 3) || (month == 5) || (month == 8) || (month == 10))
		{ 
			days = 30;
  		} else {
  			if(month != 1)
  			{
   				days = 31;
			} else {
				if((year % 4) == 0)
				{
					if(((year % 100) == 0) && ((year % 400) != 0))
   						days = 28;
   					else
   						days = 29;
   				} else {
   					days = 28;
   				}
			}
		}
			
		return days;
	};
	
	calendar._replaceCellText = function(cellElem, text)
	{
		cellElem.firstChild.nodeValue = text;
	};
	
	/* Initialization */
	calendar._monthSelect.calendar = calendar;
	calendar._monthSelect.onchange = function()
	{
		this.calendar._currentDate.setMonth(this.calendar._monthSelect.selectedIndex);
		this.calendar._update();
	};
	for(i = 0; i < 12; i++)
		calendar._monthSelect.options[i] = new Option(calendar._months[i]);

	years = calendar._endLimit.getFullYear() - calendar._startLimit.getFullYear();
	calendar._yearSelect.calendar = calendar;
	calendar._yearSelect.onchange = function()
	{
		this.calendar._currentDate.setFullYear(this.calendar._startLimit.getFullYear() + this.calendar._yearSelect.selectedIndex);
		this.calendar._update();
	};
	for(i = 0; i <= years; i++)
		calendar._yearSelect.options[i] = new Option(calendar._startLimit.getFullYear() + i);
	
	calendar._headerCells[0].calendar = calendar;
	calendar._headerCells[0].onclick = function()
	{
		this.calendar._goBackMonth();
	};
	
	calendar._headerCells[2].calendar = calendar;
	calendar._headerCells[2].onclick = function()
	{
		this.calendar._goForwardMonth();
	};
	
	for(i = 0; i < calendar._dayCells.length; i++)
	{
		calendar._dayCells[i]._cellIndex = i;
		calendar._dayCells[i]._calendar = calendar;
		calendar._dayCells[i].onclick = function()
		{
			this._calendar._setDateSelection(this._cellIndex, this._calendar._callbackFunc, this._calendar._callbackArgs);
		};
	}
	
	calendar._selectedIndex = calendar._currentDate.getDate() + 
		calendar._getFirstDayIndex() - 1;
	calendar._update();
	calendar._setDateSelection(calendar._selectedIndex, null, null);
	
	return calendar;
}

function initDate(dateString)
{
	newDate = new Date();
	newDate.setFullYear(parseInt(dateString.substring(0,4),10));
	newDate.setMonth(parseInt(dateString.substring(4,6),10) - 1);
	newDate.setDate(parseInt(dateString.substring(6,8),10));
	newDate.setHours(0);
	newDate.setMinutes(0);
	newDate.setSeconds(0);
	newDate.setMilliseconds(0);
	
	return newDate;
}

