var Cathmhaol = window.Cathmhaol || {};

/**
* @library     Cathmhaol.Calendar
* @description Extends the date object.
* @author Robert King
*
* @example  var sShortDayName = Cathmhaol.Calendar.DAYS["en"][Cathmhaol.Calendar.SUNDAY].shortName
*/
Cathmhaol.Calendar = {
	/**
	* @property     DAYS
	* @description  Hash of day names
	* @type {Array}
	*/
	DAYS: {
		"da": new Array({longName: "s&#248;ndag", shortName: "s&#248;n"}, {longName: "mandag", shortName: "man"}, {longName: "tirsdag", shortName: "tirs"}, {longName: "onsdag", shortName: "ons"}, {longName: "torsdag", shortName: "tors"}, {longName: "fredag", shortName: "fre"}, {longName: "l&#248;rdag", shortName: "l&#248;r"}),
		"de": new Array({longName: "Sonntag", shortName: "So"}, {longName: "Montag", shortName: "Mo"}, {longName: "Dienstag", shortName: "Di"}, {longName: "Mittwoch", shortName: "Mi"}, {longName: "Donnerstag", shortName: "Do"}, {longName: "Freitag", shortName: "Fr"}, {longName: "Samstag", shortName: "Sa"}),
		"en": new Array({longName: "Sunday", shortName: "Sun"}, {longName: "Monday", shortName: "Mon"}, {longName: "Tuesday", shortName: "Tue"}, {longName: "Wednesday", shortName: "Wed"}, {longName: "Thursday", shortName: "Thu"}, {longName: "Friday", shortName: "Fri"}, {longName: "Saturday", shortName: "Sat"}),
		"es": new Array({longName: "domingo", shortName: "dom"}, {longName: "lunes", shortName: "lun"}, {longName: "martes", shortName: "mar"}, {longName: "mi&#233;rcoles", shortName: "mi&#233;"}, {longName: "jueves", shortName: "jue"}, {longName: "viernes", shortName: "vie"}, {longName: "s&#225;bado", shortName: "s&#225;b"}),
		"fi": new Array({longName: "sunnuntai", shortName: "su"}, {longName: "maanantai", shortName: "ma"}, {longName: "tiistai", shortName: "ti"}, {longName: "keskiviiko", shortName: "ke"}, {longName: "torstai", shortName: "to"}, {longName: "perjantai", shortName: "pe"}, {longName: "lauantai", shortName: "la"}),
		"fr": new Array({longName: "dimanche", shortName: "dim"}, {longName: "lundi", shortName: "lun"}, {longName: "mardi", shortName: "mar"}, {longName: "mercredi", shortName: "mer"}, {longName: "jeudi", shortName: "jeu"}, {longName: "vendredi", shortName: "ven"}, {longName: "samedi", shortName: "sam"}),
		"ga": new Array({longName: "D&#233; Domhnaigh", shortName: "Dom"}, {longName: "D&#233; Luain", shortName: "Lua"}, {longName: "D&#233; M&#225;irt", shortName: "M&#225;i"}, {longName: "D&#233; Ch&#233;adaoin", shortName: "Ch&#233;"}, {longName: "D&#233;ardaoin", shortName: "Dao"}, {longName: "D&#233; hAoine", shortName: "Aoi"}, {longName: "D&#233; Sathairn", shortName: "Sat"}),
		"hu": new Array({longName: "vas&#225;map", shortName: "vas"}, {longName: "h&#233;tf&#246;", shortName: "h&#233;"}, {longName: "kedd", shortName: "ked"}, {longName: "szerda", shortName: "sze"}, {longName: "cs&#252;t&#246;rt&#246;k", shortName: "cs&#252"}, {longName: "p&#233;ntek", shortName: "p&#233;n"}, {longName: "szombat", shortName: "szo"}),
		"it": new Array({longName: "domenica", shortName: "dom"}, {longName: "lunedì", shortName: "lun"}, {longName: "martedì", shortName: "mar"}, {longName: "mercoledì", shortName: "mer"}, {longName: "giovedì", shortName: "gio"}, {longName: "venerdì", shortName: "ven"}, {longName: "sabato", shortName: "sab"}),
		"nl": new Array({longName: "zondag", shortName: "zondag"}, {longName: "maandag", shortName: "maan-"}, {longName: "dinsdag", shortName: "dins-"}, {longName: "woensdag", shortName: "woens-"}, {longName: "donderdag", shortName: "donder-"}, {longName: "vrijdag", shortName: "vrij-"}, {longName: "zaterdag", shortName: "zat-"}),
		"pl": new Array({longName: "niedziela", shortName: "nie"}, {longName: "poniedzia&#322;ek", shortName: "pon"}, {longName: "wtorek", shortName: "wto"}, {longName: "&#347;roda", shortName: "&#347;rd"}, {longName: "czwartek", shortName: "czw"}, {longName: "pi&#261;tek", shortName: "pi&#261;"}, {longName: "sobota", shortName: "sob"}),
		"pt": new Array({longName: "domingo", shortName: "dom"}, {longName: "segunda-feira", shortName: "seg"}, {longName: "ter&#231;a-feira", shortName: "ter"}, {longName: "quarta-feira", shortName: "qua"}, {longName: "quinta-feira", shortName: "qui"}, {longName: "sexta-feira", shortName: "sex"}, {longName: "s&#225;bado", shortName: "s&#225;"}),
		"sv": new Array({longName: "s&#246;ndag", shortName: "s&#246;n"}, {longName: "m&#229;ndag", shortName: "m&#229;n"}, {longName: "tisdag", shortName: "tis"}, {longName: "onsdag", shortName: "ons"}, {longName: "torsdag", shortName: "tors"}, {longName: "fredag", shortName: "fre"}, {longName: "l&#246;rdag", shortName: "l&#246;r"})
	},

	/**
	* @method       dateAdd
	* @description  Returns a date after adding the specified period
	* @returns {date}
	* @param {string} interval            One of y(ear), q(uarter), m(onth), d(ay), w(eek), h(our), (mi)n(ute), s(econd)
	* @param {integer} numberOfIntervals  The number of intervals to add
	* @param {string|date} startDate      The base date
	*/
	dateAdd: function(interval, numberOfIntervals, startDate) {
		if (typeof startDate == "string") { startDate = new Date(startDate); }
		switch (interval.toLowerCase()) {
			case "d": return new Date(startDate.setDate(startDate.getDate() + parseFloat(numberOfIntervals)));
			case "h": return new Date(startDate.setHours(startDate.getHours() + parseFloat(numberOfIntervals)));
			case "m": return new Date(startDate.setMonth(startDate.getMonth() + parseFloat(numberOfIntervals)));
			case "n": return new Date(startDate.setMinutes(startDate.getMinutes() + parseFloat(numberOfIntervals)));
			case "q": return new Date(startDate.setMonth(startDate.getMonth() + (parseFloat(numberOfIntervals) * 3)));
			case "s": return new Date(startDate.setSeconds(startDate.getSeconds() + parseFloat(numberOfIntervals)));
			case "w": return new Date(startDate.setDate(startDate.getDate() + (parseFloat(numberOfIntervals) * 7)));
			case "y": return new Date(startDate.setFullYear(startDate.getFullYear() + parseFloat(numberOfIntervals)));
		}
		return;
	},

	/**
	* @method       dateDiff
	* @description  Returns the number of specified intervals between the start date and the end date.
	* @returns {float}
	* @param {string} interval        One of y(ear), q(uarter), m(onth), d(ay), w(eek), h(our), (mi)n(ute), s(econd)
	* @param {string|date} startDate  The starting date
	* @param {string|date} endDate    The ending date
	*/
	dateDiff: function(interval, startDate, endDate) {
		if (typeof startDate == "string") { startDate = new Date(startDate); }
		if (typeof endDate == "string") { endDate = new Date(endDate); }
		switch (interval.toLowerCase()) {
			case "d": return ((endDate.getTime() - startDate.getTime())/(1000 * 60 * 60 * 24));
			case "h": return ((endDate.getTime() - startDate.getTime())/(1000 * 60 * 60));
			case "m": return ((endDate.getFullYear() - startDate.getFullYear())*12) + (endDate.getMonth() - startDate.getMonth());
			case "n": return ((endDate.getTime() - startDate.getTime())/(1000 * 60));
			case "q": return ((endDate.getFullYear() - startDate.getFullYear())*4) + ((endDate.getMonth() - startDate.getMonth())/4);
			case "s": return ((endDate.getTime() - startDate.getTime())/1000);
			case "w": return ((endDate.getTime() - startDate.getTime())/(1000 * 60 * 60 * 24 * 7));
			case "y": return endDate.getFullYear() - startDate.getFullYear();
		}
		return;
	},

	/**
	* @method       dayOfTheWeek
	* @description  Returns the day of the week
	* @returns {integer}
	* @param {date} d  A date.
	*/
	dayOfTheWeek: function(d) {
		if (d) {
			return d.getDay();
		}
		return;
	},

	/**
	* @method       daysInMonth
	* @description  Calculates the number of days in a month.
	* @returns {integer}
	* @param {date} d  A date
	*/
	daysInMonth: function(d) {
		if (d) {
			switch (d.getMonth()) {
				case 1: if (this.isLeapYear(d.getFullYear())) { return 29; } else { return 28; }
				case 3:
				case 5:
				case 8:
				case 10: return 30;
				default: return 31; 
			}
		}
		return;
	},

	/**
	* @property     FRIDAY
	* @description  Constant numeric value of Friday
	* @type {integer}
	*/
	FRIDAY: 5,

	/**
	* @method       isLeapYear
	* @description  Returns true if the year evaluated is a leap year.
	* @returns {boolean}
	*/
	isLeapYear: function(iYear) {
		if (!iYear || iYear < 1) { return false; }
		return ((iYear % 4 == 0) && (iYear % 100 != 0)) || (iYear % 400 == 0);
	},

	/**
	* @method       isSupportedLanguage
	* @description  Returns true if the specified language code is supported.
	* @returns {boolean}
	* @param {string} languageCode  A language code.
	*/
	isSupportedLanguage: function(languageCode) {
		for (var langCode in this.DAYS) {
			if (langCode.toLowerCase() == languageCode.toLowerCase()) {
				return true;
			}
		}
		return false;
	},

	/**
	* @property     MONDAY
	* @description  Constant numeric value of Monday
	* @type {integer}
	*/
	MONDAY: 1,

	/**
	* @property     MONTHS
	* @description  Hash of month names
	* @type {Array}
	*/
	MONTHS: {
		"da": new Array({longName: "Januar", shortName: "jan"}, {longName: "Februar", shortName: "feb"}, {longName: "Marts", shortName: "mar"}, {longName: "April", shortName: "apr"}, {longName: "Maj", shortName: "maj"}, {longName: "Juni", shortName: "jun"}, {longName: "Juli", shortName: "jul"}, {longName: "August", shortName: "aug"}, {longName: "September", shortName: "sep"}, {longName: "Oktober", shortName: "okt"}, {longName: "November", shortName: "nov"}, {longName: "December", shortName: "dec"}),
		"de": new Array({longName: "Januar", shortName: "Jan"}, {longName: "Februar", shortName: "Feb"}, {longName: "M&#228;rz", shortName: "M&#228;rz"}, {longName: "April", shortName: "Apr"}, {longName: "Mai", shortName: "Mai"}, {longName: "Juni", shortName: "Juni"}, {longName: "Juli", shortName: "Juli"}, {longName: "August", shortName: "Aug"}, {longName: "September", shortName: "Sept"}, {longName: "Oktober", shortName: "Okt"}, {longName: "November", shortName: "Nov"}, {longName: "Dezember", shortName: "Dez"}),
		"en": new Array({longName: "January", shortName: "Jan"}, {longName: "February", shortName: "Feb"}, {longName: "March", shortName: "Mar"}, {longName: "April", shortName: "Apr"}, {longName: "May", shortName: "May"}, {longName: "June", shortName: "Jun"}, {longName: "July", shortName: "Jul"}, {longName: "August", shortName: "Aug"}, {longName: "September", shortName: "Sep"}, {longName: "October", shortName: "Oct"}, {longName: "November", shortName: "Nov"}, {longName: "December", shortName: "Dec"}),
		"es": new Array({longName: "enero", shortName: "ene"}, {longName: "febrero", shortName: "feb"}, {longName: "marzo", shortName: "mar"}, {longName: "abril", shortName: "abr"}, {longName: "mayo", shortName: "may"}, {longName: "junio", shortName: "jun"}, {longName: "julio", shortName: "jul"}, {longName: "agosto", shortName: "ago"}, {longName: "septiembre", shortName: "sep"}, {longName: "octubre", shortName: "oct"}, {longName: "noviembre", shortName: "nov"}, {longName: "diciembre", shortName: "dic"}),
		"fi": new Array({longName: "tammikuu", shortName: "tammik."}, {longName: "helmikuu", shortName: "helmik."}, {longName: "maaliskuu", shortName: "maalisk."}, {longName: "huhtikuu", shortName: "huhtik."}, {longName: "toukokuu", shortName: "toukok."}, {longName: "kes&#228;kuu", shortName: "kes&#228;k."}, {longName: "hein&#228;kuu", shortName: "hein&#228;k."}, {longName: "elokuu", shortName: "elok."}, {longName: "syyskuu", shortName: "syysk."}, {longName: "lokakuu", shortName: "lokak."}, {longName: "marraskuu", shortName: "marrask."}, {longName: "joulukuu", shortName: "jouluk."}),
		"fr": new Array({longName: "janvier", shortName: "janv"}, {longName: "f&#232;vrier", shortName: "f&#232;vr"}, {longName: "mars", shortName: "mars"}, {longName: "avril", shortName: "avril"}, {longName: "mai", shortName: "mai"}, {longName: "juin", shortName: "juin"}, {longName: "juillet", shortName: "juil"}, {longName: "ao&#251;t", shortName: "ao&#251;t"}, {longName: "septembre", shortName: "sept"}, {longName: "octobre", shortName: "oct"}, {longName: "novembre", shortName: "nov"}, {longName: "d&#232;cembre", shortName: "d&#232;c"}),
		"ga": new Array({longName: "M&#237; Eanair", shortName: "Ean"}, {longName: "M&#237; Feabhra", shortName: "Fea"}, {longName: "M&#237; M&#225;rta", shortName: "Mar"}, {longName: "M&#237; Aibre&#225;n", shortName: "Aib"}, {longName: "M&#237; Bealtaine", shortName: "Bea"}, {longName: "M&#237; Meitheamh", shortName: "Mei"}, {longName: "M&#237; I&#250;il", shortName: "I&#250;l"}, {longName: "M&#237; L&#250;nasa", shortName: "L&#250;n"}, {longName: "M&#237; Me&#225;n Fomhair", shortName: "Mfo"}, {longName: "M&#237; Deireadh Fomhair", shortName: "Dfo"}, {longName: "M&#237; na Samhna", shortName: "Sam"}, {longName: "M&#237; na Nollag", shortName: "Nol"}),
		"hu": new Array({longName: "janu&#225;r", shortName: "jan"}, {longName: "febru&#225;r", shortName: "feb"}, {longName: "m&#225;rcius", shortName: "m&#255;"}, {longName: "&#225;prilis", shortName: "&#255;pr"}, {longName: "m&#225;jus", shortName: "m&#255;j"}, {longName: "j&#250;nius", shortName: "j&#250;n"}, {longName: "j&#250;lius", shortName: "j&#250;l"}, {longName: "augusztus", shortName: "aug"}, {longName: "szeptember", shortName: "sep"}, {longName: "okt&#243;ber", shortName: "okt"}, {longName: "november", shortName: "nov"}, {longName: "december", shortName: "dec"}),
		"it": new Array({longName: "gennaio", shortName: "gen"}, {longName: "febbraio", shortName: "feb"}, {longName: "marzo", shortName: "mar"}, {longName: "aprile", shortName: "apr"}, {longName: "maggio", shortName: "mag"}, {longName: "giugno", shortName: "giu"}, {longName: "luglio", shortName: "lug"}, {longName: "agosto", shortName: "ago"}, {longName: "settembre", shortName: "sett"}, {longName: "ottobre", shortName: "ott"}, {longName: "novembre", shortName: "nov"}, {longName: "dicembre", shortName: "dic"}),
		"nl": new Array({longName: "januari", shortName: "jan"}, {longName: "februari", shortName: "feb"}, {longName: "mart", shortName: "mrt"}, {longName: "april", shortName: "apr"}, {longName: "mei", shortName: "mei"}, {longName: "juni", shortName: "jun"}, {longName: "juli", shortName: "jul"}, {longName: "augustus", shortName: "aug"}, {longName: "september", shortName: "sep"}, {longName: "oktober", shortName: "okt"}, {longName: "november", shortName: "nov"}, {longName: "december", shortName: "dec"}),
		"pl": new Array({longName: "stycze&#324;", shortName: "sty"}, {longName: "luty", shortName: "luty"}, {longName: "marzec", shortName: "mar"}, {longName: "kwiecie&#324;", shortName: "kwi"}, {longName: "maj", shortName: "maj"}, {longName: "czerwiec", shortName: "cze"}, {longName: "lipiec", shortName: "lip"}, {longName: "sierpie&#324;", shortName: "sier"}, {longName: "wrzesie&#324;", shortName: "wrze"}, {longName: "pa&#378;dziernik", shortName: "pa&#378;"}, {longName: "listopad", shortName: "list"}, {longName: "grudzie&#324;", shortName: "gru"}),
		"pt": new Array({longName: "janeiro", shortName: "jan"}, {longName: "fevereiro", shortName: "fev"}, {longName: "mar&#231;o", shortName: "mar"}, {longName: "abril", shortName: "abr"}, {longName: "maio", shortName: "mai"}, {longName: "junho", shortName: "jun"}, {longName: "julho", shortName: "jul"}, {longName: "agosto", shortName: "ago"}, {longName: "setembro", shortName: "set"}, {longName: "outubro", shortName: "out"}, {longName: "novembro", shortName: "nov"}, {longName: "dezembro", shortName: "dez"}),
		"sv": new Array({longName: "januari", shortName: "jan"}, {longName: "februari", shortName: "febr"}, {longName: "mars", shortName: "mars"}, {longName: "april", shortName: "april"}, {longName: "maj", shortName: "maj"}, {longName: "juni", shortName: "juni"}, {longName: "juli", shortName: "juli"}, {longName: "augusti", shortName: "aug"}, {longName: "september", shortName: "sept"}, {longName: "october", shortName: "okt"}, {longName: "november", shortName: "nov"}, {longName: "december", shortName: "dec"})
	},

	/**
	* @method       ordinalDate
	* @description  Returns an ordinal date. For example, ordinalDate(2008, 2, 5, Cathmhaol.Calendar.SUNDAY) would return the fifth Sunday in March, 2008 -- 30-MAR-08.
	* @returns {date}
	* @param {integer} yy  Year
	* @param {integer} mm  Zero-based month index
	* @param {integer} oi  Ordinal index - must be 1 (first), 2 (second), 3 (third), 4 (fourth), or 5 (fifth)
	* @param {integer} dd  Day of the week
	*/
	ordinalDate: function(yy, mm, oi, dd) {
		var min = ((oi - 1) * 7) + 1;
		var max = min + 7;
		for (var c = min; c <= max; c++) {
			var d = new Date(yy, mm, c);
			if (d.getDay() == dd) { return d; }
		}
		return;
	},

	/**
	* @property     SATURDAY
	* @description  Constant numeric value of Saturday
	* @type {integer}
	*/
	SATURDAY: 6,

	/**
	* @property     SUNDAY
	* @description  Constant numeric value of Sunday
	* @type {integer}
	*/
	SUNDAY: 0,

	/**
	* @property     THURSDAY
	* @description  Constant numeric value of Thursday
	* @type {integer}
	*/
	THURSDAY: 4,

	/**
	* @property     TUESDAY
	* @description  Constant numeric value of Tuesday
	* @type {integer}
	*/
	TUESDAY: 2,

	/**
	* @property     WEDNESDAY
	* @description  Constant numeric value of Wednesday
	* @type {integer}
	*/
	WEDNESDAY: 3
}
