// daysInMonth - returns the number of days in iMonth (zero based index) and iYear by using the fact that overflowing a given month's number of days returns the date of the following month
function daysInMonth(iMonth, iYear)
{
	return 32 - new Date(iYear, iMonth, 32).getDate();
}

// displayMonth - displays a table with the current month and a list days with links
// Week in the calendar begins on a sunday
function displayMonth()
{
  	date = new Date();
  	var this_day = date.getDay();
	var this_date = date.getDate();
	var this_month = date.getMonth();
	var this_year = date.getFullYear();
	
	var months = new Array("January", "February", "March", 	"April", "May", "June", "July", "August", "September", "October", "November", "December");
	
	fullDate = new Date(this_year, this_month, 1);		// date when month begins
	vWeekday = fullDate.getDay();				// day of the week when month begins
	
	document.write("<table class=\"cal_tiny\" cellpadding=\"0\" cellspacing=\"0\">");
	document.write("<tr><th colspan='7'><a href='./programs/calendar/nav/?year="+this_year+"&month="+(this_month+1)+"&content=grid'>" + months[this_month] + " " + this_year + "</a></th></tr>");
	
	var counter = 0;					// counts cells
	var dateNow = 1;					// counts dates
	var dateMax = daysInMonth(this_month, this_year);
		
	while(dateNow <= dateMax){
		if (counter % 7 == 0) document.write("<tr>");	// start the row
		while(vWeekday > counter){			// fill with empty cells until reaches beginning of month
			document.write('<td>&nbsp;</td>');
			counter++;
		}
		if (checkHoliday(1, dateNow, this_month, this_year)) document.write("<td class=\"cal_holiday\">");	// mark as holiday
		else if ((counter % 7 == 0) || (counter % 7 == 6)) document.write("<td class=\"cal_weekend\">");	// mark as weekend
		else document.write("<td>");
		
		// add a link to current month's calendar
		document.write("<a href='./programs/calendar/nav/?year="+this_year+"&month="+(this_month+1)+"&content=grid'>"+dateNow+"</a>");
		document.write("</td>");
		
		if(counter % 7 == 6) document.write("</tr>");	// finish the row
		
		else if(dateNow == dateMax){			// fill with empty cell until reaches end of row
			while(counter % 7 != 6){
				document.write("<td></td>");
				counter++;
			}
			document.write("</tr>");
		}
		
		dateNow++;
		counter++;
	}
	document.write('</table>');
}

function checkHolidayz(this_day, this_date, this_month, this_year){
	return true;
}

function checkHoliday(this_day, this_date, this_month, this_year) {

	// January is month 0
	if(this_month == 0){
		// new  year day
		if(this_date == 1) return true;
		// martin luther king day
		holidayDate = getHoliday(this_year, this_month, 1, 3); // 1 - monday, 3 - martin luther is 3rd monday
		if(this_date == holidayDate) return true;

	}

	// February is month 1
	else if(this_month == 1){
		// presidents day
		holidayDate = getHoliday(this_year, this_month, 1, 3); // 1 - monday, 3 - presidents day is 3rd monday
		if(this_date == holidayDate) return true;
	}

	// March is month 2
	else if(this_month == 2){
		// possibly Easter
		var easter = getEaster(this_year);
		easter_month = easter[0];
		easter_date = easter[1];

		// check number of days remaining to Easter
		easterCountdown = -1; // default value which gets reset if applicable
		if(easter_month == 2){easterCountdown = easter_date - this_date;}
		if(easterCountdown == 0) return true; // getEaster function already calculated a Sunday date, so no checking is needed here

	}

	// April is month 3
	else if(this_month == 3){
		// possibly Easter
		var easter = getEaster(this_year);
		easter_month = easter[0];
		easter_date = easter[1];

		// check number of days remaining to Easter
		easterCountdown = -1; // default value which gets reset if applicable
		if(easter_month == 3){easterCountdown = easter_date - this_date;}
		if(easterCountdown == 0) return true;
		
		// presidents day
		holidayDate = getHoliday(this_year, this_month, 1, 3); // 1 - monday, 3 - patriots day is 3rd april
		if(this_date == holidayDate) return true;
	}

	// May is month 4
	else if(this_month == 4){
		// memorial day (library is also closed on memorial weekend sunday)
		if (this_date >= 17 && this_date <= 31){
			holidayDate = getHoliday(this_year, this_month, 1, 5); // 1 - monday, 5 - memorial day is last monday (see getHoliday)
			if((this_date == holidayDate-1) || (this_date == holidayDate)) return true;
		}
	}

	// June is month 5
	else if(this_month == 5){
		return false;
	}

	// July is month 6
	else if(this_month == 6){
		if (this_date >= 3 && this_date <= 5){
			var indep = getDatedHoliday(this_year, this_month, 4, "weekday"); // find weekday for july 4th
			indepDay = indep[1]; // day of the week
			indepDate = indep[0]; // date of the month (usually the 4th)
			if (this_date == indepDate) return true;
			else if ((this_date == (indepDate + 1)) && (indepDay == 5) && (indepDate == 3)) return true;
			else if ((this_date == (indepDate - 1)) && (indepDay == 6) && (indepDate == 5)) return true;
		}		
	}

	// August is month 7
	else if(this_month == 7){
		return false;
	}


	// September is month 8
	else if(this_month == 8){
		// labor day (library is also closed on labor day weekend saturday and sunday)
		if	(this_date <= 7){
			holidayDate = getHoliday(this_year, this_month, 1, 1); // 1 - monday, 1 - labor day is 1st monday in september
			laborCountdown = (holidayDate - this_date);
			if(laborCountdown <= 2 && laborCountdown >= 0) return true;
		}
	}

	// October is month 9
	else if(this_month == 9){
		// columbus day
		if	(this_date >= 1 && this_date <= 14){
			holidayDate = getHoliday(this_year, this_month, 1, 2); // 1 - monday, 2 - columbus day is second monday
			if(this_date == holidayDate) return true;
		}
	}

	// November is month 10
	else if(this_month == 10){
		// veterans day, typically the 11th of November (if 11th falls on Saturday, moved to Friday 10th; if 11th falls on Sunday, moved to Monday 12th).
		if	(this_date >= 3 && this_date <= 12){
			var veterans = getDatedHoliday(this_year, this_month, 11, 'weekday'); // find veterans date and day of the week
			veteransDate = veterans[0]; // usually the 11th
			veteransDay = veterans[1]; // day of the week

			if(this_date == veteransDate) return true;
		}
		// thanksgiving
		else if	(this_date >= 16 && this_date <= 28){
			holidayDate = getHoliday(this_year, this_month, 4, 4); // 4 - thursday, 4 - thanksgiving is the 4th thursday
			if(this_date == holidayDate) return true;
		}
	} // end of November

	// December is month 11
	else if(this_month == 11){
		if	(this_date >= 18 && this_date <=25)	{
			var Christmas = getDatedHoliday(this_year, this_month, 25, 'any'); // find the Chirstmas day of the week (and date which is already known)
			ChristmasDate = Christmas[0]; // always the 25th
			ChristmasDay = Christmas[1]; // day of the week
			if(this_date == ChristmasDate) return true;
		}		
	}

	return false;
	
} //end display date


// input: year, month, day of the week, the occurance of day of the week being thought (use 5 for "last")
// output: date of the holiday occuring on in that year, month, day specified in input
// reference http://michaelthompson.org/technikos/holidays.php
function getHoliday(year, month, targetDay, dayNumber){
	earliestDate = 1 + 7 * (dayNumber - 1);
	fullDate = new Date(year, month, earliestDate);// date to be used to help find the weekday
	weekday = fullDate.getDay();// temp weekday matching the earliestDate
	
	if(targetDay == weekday){
		offset = 0;}
	else{
		if(targetDay < weekday){
			offset = targetDay + (7 - weekday);}
		else{
			offset = (targetDay + (7 - weekday)) - 7;}
	}
	
	holidayDate = earliestDate + offset;
	if(holidayDate > 31) holidayDate -= 7; // this is for "last" weekday of month if the date exceeds length of 31-day month
	return holidayDate;	
}

// input: year
// output: date and day of the week
// veterans is on November 11th; if 11th falls on Saturday, it is moved to Friday 10th; if 11th falls on Sunday, it is moved to Monday 12th
// desired_day can adjust date and day of the week if, for example, a weekday is specified
function getDatedHoliday(year, vMonth, vDate, desired_day){

	fullDate = new Date(year, vMonth, vDate); // date to be used to help find the weekday
	vWeekday = fullDate.getDay();// temp weekday matching the vDate
	offset = 0; // default offset; gets modified if a holiday should not happen on a weekend
	if(desired_day == 'weekday'){
		if(vWeekday == 0){offset = 1;} // if 11th falls on sunday[0], move veterans one day up to monday nov 12th 
		else if(vWeekday == 6){offset = -1;} // if 11th falls on saturday[6], move veterans one day earlier to friday nov 10th
	}
	vDate = vDate + offset;
	vWeekday = vWeekday + offset;
	
	var holiday = [vDate, vWeekday];
	return holiday;	
}

// calculates Easter using Carter's algorithm; returns a [month, date] array.
// The Oudin algorithm is valid for all years in the Gregorian calendar, 1583 and onwards. The Carter algorithm is simpler but only works in two centuries, 1900 through 2099.
// The web site source for Easter algorithms (and extensive discussion of holidays in general) is http://smart.net/~mmontes/ec-cal.html by Marcos J. Montes.
function getEaster(y) {
	month = 0; // this will be reset
	step01 = 225 - 11 * (y % 19);
	step02 = ((step01 - 21) % 30) + 21;
	if(step02 > 48) step02 = step02 - 1;
	step03 = (y + parseInt(y/4) + step02 + 1) % 7;
	date = step02 + 7 - step03;
	if(date <= 31){
		month = 2; // march
	}
	else{ 
		month = 3; // april
		date = date - 31;		
	}
	var easter = [month, date];
	return easter;
}

displayMonth();
