/*
	Month Calendar - A Monthly Calendar with Week Numbers
	Copyright © 2005-2008 Harry Whitfield

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License as
	published by the Free Software Foundation; either version 2 of
	the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public
	License along with this program; if not, write to the Free
	Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
	MA  02110-1301  USA
	
	Month Calendar - version 2.4
	12 March, 2008
	Copyright © 2005-2008 Harry Whitfield
	mailto:g6auc@arrl.net
*/

function getDateOfFirst(dayName, date, monthName, year)
{
	// get Date (1..31) Of First dayName (Sun..Sat) after date (1..31) of monthName (Jan..Dec) of year (2004..)

	// dayName: 	Sun, Mon, Tue, Wed, Thu, Fr, Sat
	// monthName:	Jan, Feb, etc.

	var day   = numberOfDay(dayName);
	var month = numberOfMonth(monthName);

	//var last  = getDaysIn(month, year);

	var last = date + 6;

	var d = new Date(year, month, last);

	var lastDay = d.getDay();

	return last - (lastDay - day + 7) % 7;
}

function getDateOfLast(dayName, monthName, year)
{
	// get Date (1..31) Of Last dayName (Sun..Sat) of monthName (Jan..Dec) of year (2004..)

	// dayName: 	Sun, Mon, Tue, Wed, Thu, Fr, Sat
	// monthName:	Jan, Feb, etc.

	var day   = numberOfDay(dayName);
	var month = numberOfMonth(monthName);

	var last  = getDaysIn(month, year);

	var d = new Date(year, month, last);

	var lastDay = d.getDay();

	return last - (lastDay - day + 7) % 7;
}

function numberOfMonth(month)
{
	var monthName =['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];

	for(var i = 0; i < 12; i += 1) { if (month == monthName[i]) { return i; } }
	print("numberOfMonth: " + month + " is not a valid month name");
	return 0;
}

function numberOfDay(day)
{
	var dayName =['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];

	for(var i = 0; i < 7; i += 1) { if (day == dayName[i]) { return i; } }
	print("numberOfDay: " + day + " is not a valid day name");
	return 0;
}

function getDaysIn(month, year)
{
	var monthDays =[31,28,31,30,31,30,31,31,30,31,30,31];

	if (month != 1) { return monthDays[month]; }

	if ((year %   4) !== 0) { return 28; }
	if ((year % 400) === 0) { return 29; }
	if ((year % 100) === 0) { return 28; }
	return 29;
}

function dayOfMonth(monthName, dayRule, year)
{
	var dayName, date;
	var day   = parseInt(dayRule, 10);

	if ( ! isNaN(day) ) { return day; }

	// dayRule of form lastThu or Sun>=15

	if (dayRule.indexOf("last") === 0)	// dayRule of form lastThu
	{
		dayName = dayRule.substring(4);

		return getDateOfLast(dayName, monthName, year);
	}
	else	// dayRule of form Sun>=15
	{
		dayName = dayRule.substring(0,3);
		date = Number(dayRule.substring(5));

		return getDateOfFirst(dayName, date, monthName, year);
	}
}

function makeRule(monthDay, weekDay)
{
	var dayRule;
	
	if (weekDay.indexOf("First") === 0)
	{
		dayRule = weekDay.substring(6,9) + ">=" + monthDay;	// Sun>=15
	}
	else if (weekDay.indexOf("Last") === 0)
	{
		dayRule = "last" + weekDay.substring(5,8);			// lastSun
	}
	else { dayRule = monthDay; }							// 15
	
	return dayRule;
}

function customWeekOfYear(year, month, day)	// month 1..12
{
	var startMonth = preferences.startMonthPref.value;	// "January", etc.
	var monthDay   = preferences.monthDayPref.value;	// "1", "2",  etc.
	var weekDay    = preferences.weekDayPref.value;		// "First Tuesday on or after", etc.
	var monthName  = startMonth.substring(0,3);			// "Jan", etc.
	var dayRule    = makeRule(monthDay, weekDay);		// "lastSun", "Mon>=15", etc.

	var refYear    = year;								// 2006
	var refMonth   = numberOfMonth(monthName);			// 0..12
	var refDay     = dayOfMonth(monthName, dayRule, refYear);
	var refDate    = new Date(refYear, refMonth,  refDay).getTime();
	
	var theDate    = new Date(year,    month - 1, day).getTime();

	if (theDate < refDate)
	{
		refYear    = year - 1;							// 2005
		refDay     = dayOfMonth(monthName, dayRule, refYear);
		refDate    = new Date(refYear, refMonth,  refDay).getTime();
	}

	var days = ((theDate - refDate) / 86400000);
	var week = Math.floor(days/7 + 0.07) + 1;
	return week;
}
