/*  
 * -----------------------------------------------------------
 * Calendar Upgrades to meet specifications set by 
 * Reliance Network
 *
 * -----------------------------------------------------------
 */

/** The Calendar object new Parameters */

// BEGIN: PARAMETERS
Calendar.prototype.minYear = 1979;
Calendar.prototype.maxYear = 2015;
Calendar.prototype.ttDateFormat = "%b %d, %Y";
Calendar.prototype.showAbout = true;
Calendar.prototype.showFooter = true;
Calendar.prototype.showHelp = true;
Calendar.prototype.disableFDSwitch = false;
Calendar.prototype.disableDrag = false;
// END: PARAMETERS


// BEGIN: CALENDAR STATIC FUNCTIONS

/** Internal -- adds a set of events to make some element behave like a button. */
// event handlers

//updated dayMouseDown
Calendar.dayMouseDown = function(ev) {
	var el = Calendar.getElement(ev);
	if (el.disabled) {
		return false;
	}
	var cal = el.calendar;
	cal.activeDiv = el;
	Calendar._C = cal;
	if(el.navtype != 300) with (Calendar){
		if (el.navtype == 50) {
			el._current = el.innerHTML;
			addEvent(document, "mousemove", tableMouseOver);
		} else
			addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
		addClass(el, "hilite active");
		addEvent(document, "mouseup", tableMouseUp);
	}else if(cal.isPopup && !cal.disableDrag){
		cal._dragStart(ev);
	}
	if(el.navtype == -1 || el.navtype == 1){
		if (cal.timeout) clearTimeout(cal.timeout);
		cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
	} else if (el.navtype == -2 || el.navtype == 2) {
		if (cal.timeout) clearTimeout(cal.timeout);
		cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
	} else {
		cal.timeout = null;
	}
	return Calendar.stopEvent(ev);
};

Calendar.dayMouseOver = function(ev) {
	var el = Calendar.getElement(ev);
	if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
		return false;
	}
	if (el.ttip && el.calendar.showHelp) {
		if (el.ttip.substr(0, 1) == "_") {
			el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
		}
		el.calendar.tooltips.innerHTML = el.ttip;
	}
	//apply event to any navtype not 300
	//	or 400 if this.showAbout is false
	if(el.navtype != 300 || (el.navtype == 400 && !this.showAbout)) {
		Calendar.addClass(el, "hilite");
		if (el.caldate) {
			Calendar.addClass(el.parentNode, "rowhilite");
		}
	}
	return Calendar.stopEvent(ev);
};

/**
 *  A generic "click" handler :) handles all types of buttons defined in this
 *  calendar.
 */
Calendar.cellClick = function(el, ev) {
	var cal = el.calendar;
	var closing = false;
	var newdate = false;
	var date = null;
	
	if (typeof el.navtype == "undefined") { //when a day is clicked
		if (cal.currentDateEl) {
			Calendar.removeClass(cal.currentDateEl, "selected");
			Calendar.addClass(el, "selected");
			closing = (cal.currentDateEl == el);
			if (!closing) {
				cal.currentDateEl = el;
			}
		}
		cal.date.setDateOnly(el.caldate);
		date = cal.date;
		
		var other_month = !(cal.dateClicked = !el.otherMonth);
		
		if (!other_month && !cal.currentDateEl)
			cal._toggleMultipleDate(new Date(date));
		else
			newdate = !el.disabled;
			
		// a date in another month was clicked
		if (other_month)
			cal._init(cal.firstDayOfWeek, date);
	} else {
		if (el.navtype == 200) { //close type
			Calendar.removeClass(el, "hilite");
			cal.callCloseHandler();
			return;
		}
		date = new Date(cal.date);
		if (el.navtype == 0){
			if(!date.compareDateOnly(new Date())){//select today (dont close incase of browsing dates)
				cal.dateClicked = false;
				newdate = true;
				date.setDateOnly(new Date()); // TODAY
				
			}else{ //close calendar and update date to today
				cal.dateClicked = true;
				closing = true;
			}
		}
		// unless "Today" was clicked, we assume no date was clicked so the selected 
		// handler will know not to close the calenar when in single-click mode.
		
		var year = date.getFullYear();
		var mon = date.getMonth();
		
		function setMonth(m) {
			var day = date.getDate();
			var max = date.getMonthDays(m);
			if (day > max) {
				date.setDate(max);
			}
			date.setMonth(m);
		};
		switch (el.navtype) {
		    case 400: //about type
				if(cal.showAbout){
					Calendar.removeClass(el, "hilite");
					var text = Calendar._TT["ABOUT"];
					if (typeof text != "undefined") {
						text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
					}
					alert(text);
					return;
				}else{
					return;
				}
				break;
			case 300: //title type
				return;
				break;
		    case -2: //prev year type
				if (year > cal.minYear) {
					date.setFullYear(year - 1);
				}
				break;
		    case -1: //prev month type
				if (mon > 0) {
					setMonth(mon - 1);
				} else if (year-- > cal.minYear) {
					date.setFullYear(year);
					setMonth(11);
				}
				break;
		    case 1: //next month type
				if (mon < 11) {
					setMonth(mon + 1);
				} else if (year < cal.maxYear) {
					date.setFullYear(year + 1);
					setMonth(0);
				}
				break;
		    case 2: //next year type
				if (year < cal.maxYear) {
					date.setFullYear(year + 1);
				}
				break;
		    case 100: //day of week type
				if(!cal.disableFDSwitch){
					cal.setFirstDayOfWeek(el.fdow);
				}
				return;
		    case 50: //time type
				var range = el._range;
				var current = el.innerHTML;
				for (var i = range.length; --i >= 0;)
					if (range[i] == current)
						break;
				if (ev && ev.shiftKey) {
					if (--i < 0)
						i = range.length - 1;
				} else if ( ++i >= range.length ){
					i = 0;
				}
				var newval = range[i];
				el.innerHTML = newval;
				cal.onUpdateTime();
				return;
		    case 0: //some type
			// TODAY will bring us here
			if ((typeof cal.getDateStatus == "function") &&
			    cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
				return false;
			}
			break;
		}
		if(!date.equalsTo(cal.date)){
			cal.setDate(date);
			newdate = true;
		}else if (el.navtype == 0){
			newdate = closing = true;
		}
	}
	if(newdate){
		ev && cal.callHandler();
	}
	if(closing){
		Calendar.removeClass(el, "hilite");
		ev && cal.callCloseHandler();
	}
};

// END: CALENDAR STATIC FUNCTIONS

// BEGIN: CALENDAR OBJECT FUNCTIONS

/**
 *  This function creates the calendar inside the given parent.  If _par is
 *  null than it creates a popup calendar inside the BODY element.  If _par is
 *  an element, be it BODY, then it creates a non-popup calendar (still
 *  hidden).  Some properties need to be set before calling this function.
 */
Calendar.prototype.create = function (_par) {
	var parent = null;
	if (! _par) {
		// default parent is the document body, in which case we create
		// a popup calendar.
		parent = document.getElementsByTagName("body")[0];
		this.isPopup = true;
	} else {
		parent = _par;
		this.isPopup = false;
	}
	this.date = this.dateStr ? new Date(this.dateStr) : new Date();

	var table = Calendar.createElement("table");
	this.table = table;
	table.cellSpacing = 0;
	table.cellPadding = 0;
	table.calendar = this;
	Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);

	var div = Calendar.createElement("div");
	this.element = div;
	div.className = "calendar";
	if (this.isPopup) {
		div.style.position = "absolute";
		div.style.display = "none";
	}
	div.appendChild(table);

	var thead = Calendar.createElement("thead", table);
	var cell = null;
	var row = null;

	var cal = this;
	var hh = function (text, cs, navtype) {
		cell = Calendar.createElement("td", row);
		cell.colSpan = cs;
		if (navtype != 0 && Math.abs(navtype) <= 2)
			cell.className += " nav";
		
		//olny apply the following if they are not an about or title element
		if((navtype != 400 && navtype != 300) || (navtype == 400 && this.showAbout)){
			cell.className = "button";	//button style add to element
			Calendar._add_evs(cell);	//add events to the current cell
			cell.innerHTML = "<div unselectable='on'>" + text + "</div>"; //cause the cell to be unselectable (breaks if added to a not event cell)
		}
		cell.calendar = cal;
		cell.navtype = navtype;
		return cell;
	};

	row = Calendar.createElement("tr", thead);
	var title_length = 6;
	(this.isPopup) && --title_length;
	(this.weekNumbers) && ++title_length;
	
	if(this.showAbout){
	hh("?", 1, 400).ttip = Calendar._TT["INFO"];
	}else{
	hh(" ", 1, 400).ttip = "";
	}
	
	this.title = hh("", title_length, 300);
	this.title.className = "title";
	if (this.isPopup && !this.disableDrag) {
		this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
		this.title.style.cursor = "move";
	}
	hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];

	row = Calendar.createElement("tr", thead);
	row.className = "headrow";

	this._nav_py = hh("&#x00ab;", 1, -2);
	this._nav_py.ttip = Calendar._TT["PREV_YEAR"];

	this._nav_pm = hh("&#x2039;", 1, -1);
	this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];

	this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
	this._nav_now.ttip = Calendar._TT["GO_TODAY"];

	this._nav_nm = hh("&#x203a;", 1, 1);
	this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];

	this._nav_ny = hh("&#x00bb;", 1, 2);
	this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];

	// day names
	row = Calendar.createElement("tr", thead);
	row.className = "daynames";
	if (this.weekNumbers) {
		cell = Calendar.createElement("td", row);
		cell.className = "name wn";
		cell.innerHTML = Calendar._TT["WK"];
	}
	for (var i = 7; i > 0; --i) {
		cell = Calendar.createElement("td", row);
		if (!i) {
			cell.navtype = 100;
			cell.calendar = this;
			Calendar._add_evs(cell);
		}
	}
	this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
	this._displayWeekdays();

	var tbody = Calendar.createElement("tbody", table);
	this.tbody = tbody;

	for (i = 6; i > 0; --i) {
		row = Calendar.createElement("tr", tbody);
		if (this.weekNumbers) {
			cell = Calendar.createElement("td", row);
		}
		for (var j = 7; j > 0; --j) {
			cell = Calendar.createElement("td", row);
			cell.calendar = this;
			Calendar._add_evs(cell);
		}
	}

	if (this.showsTime) {
		row = Calendar.createElement("tr", tbody);
		row.className = "time";

		cell = Calendar.createElement("td", row);
		cell.className = "time";
		cell.colSpan = 2;
		cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";

		cell = Calendar.createElement("td", row);
		cell.className = "time";
		cell.colSpan = this.weekNumbers ? 4 : 3;

		(function(){
			function makeTimePart(className, init, range_start, range_end) {
				var part = Calendar.createElement("span", cell);
				part.className = className;
				part.innerHTML = init;
				part.calendar = cal;
				part.ttip = Calendar._TT["TIME_PART"];
				part.navtype = 50;
				part._range = [];
				if (typeof range_start != "number")
					part._range = range_start;
				else {
					for (var i = range_start; i <= range_end; ++i) {
						var txt;
						if (i < 10 && range_end >= 10) txt = '0' + i;
						else txt = '' + i;
						part._range[part._range.length] = txt;
					}
				}
				Calendar._add_evs(part);
				return part;
			};
			var hrs = cal.date.getHours();
			var mins = cal.date.getMinutes();
			var t12 = !cal.time24;
			var pm = (hrs > 12);
			if (t12 && pm) hrs -= 12;
			var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
			var span = Calendar.createElement("span", cell);
			span.innerHTML = ":";
			span.className = "colon";
			var M = makeTimePart("minute", mins, 0, 59);
			var AP = null;
			cell = Calendar.createElement("td", row);
			cell.className = "time";
			cell.colSpan = 2;
			if (t12)
				AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
			else
				cell.innerHTML = "&nbsp;";

			cal.onSetTime = function() {
				var pm, hrs = this.date.getHours(),
					mins = this.date.getMinutes();
				if (t12) {
					pm = (hrs >= 12);
					if (pm) hrs -= 12;
					if (hrs == 0) hrs = 12;
					AP.innerHTML = pm ? "pm" : "am";
				}
				H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
				M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
			};

			cal.onUpdateTime = function() {
				var date = this.date;
				var h = parseInt(H.innerHTML, 10);
				if (t12) {
					if (/pm/i.test(AP.innerHTML) && h < 12)
						h += 12;
					else if (/am/i.test(AP.innerHTML) && h == 12)
						h = 0;
				}
				var d = date.getDate();
				var m = date.getMonth();
				var y = date.getFullYear();
				date.setHours(h);
				date.setMinutes(parseInt(M.innerHTML, 10));
				date.setFullYear(y);
				date.setMonth(m);
				date.setDate(d);
				this.dateClicked = false;
				this.callHandler();
			};
		})();
	} else {
		this.onSetTime = this.onUpdateTime = function() {};
	}

	if(this.showFooter){
		var tfoot = Calendar.createElement("tfoot", table);

		row = Calendar.createElement("tr", tfoot);
		row.className = "footrow";

		cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
		cell.className = "ttip";
		//disable drag
		if (this.isPopup && !this.disableDrag) {
			cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
			cell.style.cursor = "move";
		}
		this.tooltips = cell;
	}

		div = Calendar.createElement("div", this.element);
		this.monthsCombo = div;
		div.className = "combo";

	for (i = 0; i < Calendar._MN.length; ++i) {
		var mn = Calendar.createElement("div");
		mn.className = Calendar.is_ie ? "label-IEfix" : "label";
		mn.month = i;
		mn.innerHTML = Calendar._SMN[i];
		div.appendChild(mn);
	}

	div = Calendar.createElement("div", this.element);
	this.yearsCombo = div;
	div.className = "combo";
	for (i = 12; i > 0; --i) {
		var yr = Calendar.createElement("div");
		yr.className = Calendar.is_ie ? "label-IEfix" : "label";
		div.appendChild(yr);
	}

	this._init(this.firstDayOfWeek, this.date);
	parent.appendChild(this.element);
};


/** Internal function; it displays the bar with the names of the weekday. */
Calendar.prototype._displayWeekdays = function () {
	var fdow = this.firstDayOfWeek;
	var cell = this.firstdayname;
	var weekend = Calendar._TT["WEEKEND"];
	for (var i = 0; i < 7; ++i) {
		cell.className = "day name";
		var realday = (i + fdow) % 7;
		if (i) {
			cell.navtype = 100;
			cell.calendar = this;
			cell.fdow = realday;
			
			if(!this.disableFDSwitch){
				cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
				Calendar._add_evs(cell);
			}
		}
		if (weekend.indexOf(realday.toString()) != -1) {
			Calendar.addClass(cell, "weekend");
		}
		cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
		cell = cell.nextSibling;
	}
};


// BEGIN: DATE OBJECT PATCHES

/** Checks date ONLY equality */
Date.prototype.compareDateOnly = function(date){
	return (
		(this.getFullYear() == date.getFullYear()) &&
		(this.getMonth() == date.getMonth()) &&
		(this.getDate() == date.getDate())
		);
};

// END: DATE OBJECT PATCHES
