//-------------------------------------------------------------------------------------------------	
//-------------------------------------------------------------------------------------------------	
// AJAX Calendar 
// Created By: Steven Gongage 10/19/2005 (captainsteve@gmail.com)
// 
//-------------------------------------------------------------------------------------------------	

/* 
	Input: 	sDivName, [nInitMonth], [nInitYear], [sDetailsText]
		sDivName 	= required; The ID of the Div that holds the calendar table
		nInitMonth 	= optional; Inits Object Dates differently depending on argument type and value
						- DEFAULT: Today's Month
						- NUMERIC: Calendar start showing on this month
						- DATE: Calendar gets start month, year and selected date from this date
		nInitYear	= optional; If nInitMonth is not a DATE type, the calendar starts showing on this year.
						- DEFAULT: Today's Year
		
*/
function AJAXCalendar(sDivName, nInitMonth, nInitYear, sDetailsText) {


	// is.js
	
	// (c) 2001 Douglas Crockford
	// 2001 June 3
	
	
	// is
	
	// The -is- object is used to identify the browser.  Every browser edition
	// identifies itself, but there is no standard way of doing it, and some of
	// the identification is deceptive. This is because the authors of web
	// browsers are liars. For example, Microsoft's IE browsers claim to be
	// Mozilla 4. Netscape 6 claims to be version 5.
	
	var is = {};
	


//-------------------------------------------------------------------------------------------------	
//-------------------------------------------------------------------------------------------------	
// Initialization of Properties
//-------------------------------------------------------------------------------------------------	
	this.dToday = new Date;
	this.stMonthData = new Array();
	this.stMonthData.astEvents = new Array();
	this.stDisplay = new Object();

	this.bDataLoaded = false;


	// Div Name --------------------------------------------
	if ((typeof sDivName != 'string') || (sDivName.length == 0)) { exit; alert('test'); }
	this.sDivName = sDivName;
	
	// Starting Dates for Display  -------------------------
	this.stDisplay.nCurrMonth 	= this.dToday.getMonth() + 1;
	this.stDisplay.nCurrYear 	= this.dToday.getFullYear();
	
	if (typeof nInitMonth == 'object') { 			
		this.stDisplay.nCurrMonth 	= nInitMonth.getMonth() + 1;
		this.stDisplay.nCurrYear 	= nInitMonth.getFullYear();
		this.stDisplay.dSelected	= nInitMonth;
	} else {
		this.stDisplay.dSelected	= this.dToday;
		if (typeof nInitMonth == 'number') {		
			this.stDisplay.nCurrMonth = nInitMonth;
		}
		
		if (typeof nInitYear == 'number') {		
			this.stDisplay.nCurrYear = nInitYear;
		}
	}

	// Details Text ----------------------------------------
	this.stDisplay.sDetailsText = 'Mouse over a date to see events';
	if (typeof sDetailsText != 'undefined') { this.stDisplay.sDetailsText = sDetailsText }
	
	// Display Information Structure -----------------------
	this.stDisplay.nSelectedCell = 0;
	this.stDisplay.sCSSOff		= 'Calendar_Cell_Off';
	this.stDisplay.sCSSNormal	= 'Calendar_Cell_On';
	this.stDisplay.sCSSToday	= 'Calendar_Cell_Today';
	this.stDisplay.sCSSSelected	= 'Calendar_Cell_Selected';
	this.stDisplay.sCSSEvent	= 'Calendar_Cell_Event';



	// Calendar Div Elements ------------------------------------------------------------
	this.divMaster		= document.getElementById(this.sDivName);
	this.divDetailOn	= document.getElementById(this.sDivName + "_Details");
	this.divDetailOff	= document.getElementById(this.sDivName + "_DetailsOff");
	this.divMonthHeader = document.getElementById(this.sDivName + '_MonthHeader');






//-------------------------------------------------------------------------------------------------	
//-------------------------------------------------------------------------------------------------	
// DATA Related Methods
//-------------------------------------------------------------------------------------------------	
	this.fAJAXCall = function() {
		var sMonthYearKey = this.fsMonthYearKey();
		var sArguments = sMonthYearKey;
		this.bDataLoaded = false;
		
		fAJAXEventHandler = eval('cal_' + this.sDivName + '_handleAJAXResponse');
		DWREngine._execute('/Support/ajaxservices/calendar/getGoogleEvents.cfm', null, 'fGetMonthData', sArguments, fAJAXEventHandler);
		
		var sDetailsInstructions = 'Please Wait. Loading from ' + this.fsMonthAsString(this.stDisplay.nCurrMonth) + ' ' + this.stDisplay.nCurrYear + '...';
		this.fWriteToDetails(sDetailsInstructions);
	}
	
//------------------------------------------------------------------------------------------------------------
	this.handleAJAXResponse = function(qsEvents) { 
		var sMonthYearKey = this.fsMonthYearKey();
		// Cache this structure for later use
		this.stMonthData[sMonthYearKey] = new Object();
		//Object.dpDump(qsEvents);
		this.stMonthData[sMonthYearKey].astEvents = qsEvents;
		this.fWriteToDetails(this.stDisplay.sDetailsText);		// Initialize Details Text
		this.fRefreshDisplay();
		this.bDataLoaded = true;
		/*
		this.stMonthData[sMonthYearKey].astEvents = astEvents[3].VALUE;


		
		*/
	}
//------------------------------------------------------------------------------------------------------------
	this.fLoadMonthData = function() {
		var stMonth = new Object();
		var sMonthYearKey = this.fsMonthYearKey();
		
		// Check if we already have the data for this month
		if (typeof this.stMonthData[sMonthYearKey] == 'undefined') {
			// If we don't already have the data loaded, do so now
			this.fAJAXCall();
		} else {
			this.handleAJAXResponse(this.stMonthData[sMonthYearKey].astEvents);
		}
		
		return stMonth;
	}








//-------------------------------------------------------------------------------------------------	
//-------------------------------------------------------------------------------------------------	
// DISPLAY Related Methods
//-------------------------------------------------------------------------------------------------	
	this.fChangeMonth		= function(sCommand) {
		switch(sCommand) {
			case 'previous': 
				if(this.stDisplay.nCurrMonth > 1) {
					this.stDisplay.nCurrMonth--;
				} else {
					this.stDisplay.nCurrMonth = 12;
					this.stDisplay.nCurrYear--;
				}
				break;
			
			case 'next': 
				if(this.stDisplay.nCurrMonth < 12) {
					this.stDisplay.nCurrMonth++;
				} else {
					this.stDisplay.nCurrMonth = 1;
					this.stDisplay.nCurrYear++;
				}
				break;
			
		}

		this.stDisplay.nSelectedCell = 0;
		this.stDisplay.sOldStyleName = '';
		this.fComputeMonthInfo();
		this.fLoadMonthData();
		
	}

//------------------------------------------------------------------------------------------------------------
	this.fSelectCell = function(nCell) {
		if (typeof nCell == 'undefined') {
			nCell = this.fnGetCellNumberFromDate(this.stDisplay.dToday);
		}

		var divNew 			= document.getElementById(this.sDivName + "_Cell_" + nCell);
		var divNewDate 		= document.getElementById(this.sDivName + "_Cell_" + nCell + "_Date");
		var divNewEvents 	= document.getElementById(this.sDivName + "_Cell_" + nCell + "_Events");

		if (this.stDisplay.nSelectedCell > 0) { 
			var divOld = document.getElementById(this.sDivName + "_Cell_" + this.stDisplay.nSelectedCell);
			if (typeof this.stDisplay.sOldStyleName == 'undefined' || this.stDisplay.sOldStyleName == '') {
				this.stDisplay.sOldStyleName = divNew.className;	
				this.stDisplay.sOldStyleName = this.stDisplay.sCSSToday;	 // Recently added this line to keep Today style from disappearing on first mouseover
			}
			divOld.className = this.stDisplay.sOldStyleName;
		}
		this.stDisplay.dSelected = this.fdGetDateFromCellNumber(nCell);
		this.stDisplay.nSelectedCell = nCell;
		this.stDisplay.sOldStyleName = divNew.className;		
		divNew.className = this.stDisplay.sCSSSelected;

	}


//------------------------------------------------------------------------------------------------------------
	this.fDrawCells	= function() {
		var nCellNum = 0;
		var nDaysInMonth = this.fnDaysInMonth();
		var nFirstDayOfMonth = this.stDisplay.nFirstdayOfMonth
		var nFirstDayOfWeekOfMonth = this.stDisplay.nFirstDayOfWeekOfMonth;
		var nDateCount = -nFirstDayOfWeekOfMonth;
		var nLastFoundIndex = 0;
		
		// get Data for this Month -------------
		var sMonthYearKey = this.fsMonthYearKey();
		var stMonthData = this.stMonthData[sMonthYearKey];
		var astEvents = this.stMonthData[sMonthYearKey].astEvents;

		var sEventsHTML = '';
		
		
		// Loop over columns and rows
		for (var y = 0; y < 6; y++)	{
			for (var x = 0; x < 7; x++) {
				nCellNum++;
				nDateCount++;
				divCell 		= document.getElementById(sDivName + '_Cell_' + nCellNum);
				divCellDate 	= document.getElementById(sDivName + '_Cell_' + nCellNum + '_Date');
				divCellEvents 	= document.getElementById(sDivName + '_Cell_' + nCellNum + '_Events');

				sInner = '&nbsp;'
				divCell.className = this.stDisplay.sCSSOff;
				sEventsHTML = '';
				
				// If the current date is within the date range 
				if ((nDateCount > 0) && (nDateCount <= nDaysInMonth)) {
					dCurrent = new Date(this.stDisplay.nCurrYear, this.stDisplay.nCurrMonth - 1, nDateCount);
					
					sInner = nDateCount;	

					divCell.className = this.stDisplay.sCSSNormal;
					
					if (typeof astEvents != 'undefined') {
						// loop over the stMonthData to find if there is an event today
						for (nCnt = 0; nCnt < astEvents.length; nCnt++) {
							if  (astEvents[nCnt].NDAYNUM == nDateCount) {
								// Check if this Cell has an Event 
								divCell.className = this.stDisplay.sCSSEvent;
								
								sThisClass = 'Calendar_EventCategory_General';
								/*
								// The Category determines the row's class (colors)
								if (astEvents[nCnt].SCATEGORY != null) { sThisClass = 'Calendar_Detail_General' }
									else { Object.dpDump(astEvents[nCnt].SCATEGORY);  sThisClass = 'Calendar_Detail_' + astEvents[nCnt].SCATEGORY; }
								*/
								
								//sLink = astEvents[nCnt].STIMESTART + ' <a href="/index.cfm?lsFuses=department/' + astEvents[nCnt].SDEPSHORTCUT + '/' + astEvents[nCnt].NCONTENTID + '">' + astEvents[nCnt].STITLE + '</a>';
								//sEventsHTML += '<div class="EventRow"><li class="' + sThisClass + '">' + sLink + "</li></div>";
								
								if (astEvents[nCnt].BALLDAY == 'true') {
									sRowText = '* ';
								} else {
									sRowText = astEvents[nCnt].STIMESTART + ' ';
								}
								sRowText += astEvents[nCnt].STITLE;
								
								var dTarget 	= this.fdGetDateFromCellNumber(nCellNum);
								nMonth = dTarget.getMonth() + 1;
								sHref = 'index.cfm?lsFuses=Calendar/Date&sEvent=' + astEvents[nCnt].SID + '&sDate=' + nMonth + '-' + dTarget.getDate() + '-' + dTarget.getFullYear() ;
								
								sRowText = '<a href="' + sHref + '" onmousemove="cal_' + sDivName + '.fShowEventDetail(' + nCnt + ')">' + sRowText + '</a>';
								sEventsHTML += '<div class="EventRow">' + sRowText + '</div>';
								
							}

						}
					
					}

					// Check for Special Dates
					if (dCurrent.getFullYear() == this.dToday.getFullYear() 
						&& dCurrent.getMonth() == this.dToday.getMonth() 
						&& dCurrent.getDate() == this.dToday.getDate()) {
						// Check if this date is TODAY 
						divCell.className = this.stDisplay.sCSSToday;
					} 
					

				}
				
				// The Cell's Date Line
				divCellDate.innerHTML 	= sInner;
				// The Cell's Events
				divCellEvents.innerHTML = sEventsHTML;
			}
			
		}
	}
	
//------------------------------------------------------------------------------------------------------------

	this.fDateClick	= function(nCellNum) {
		var dTarget 	= this.fdGetDateFromCellNumber(nCellNum);
		if (typeof(dTarget) == 'object') {
			nMonth = dTarget.getMonth() + 1;
			window.location = 'index.cfm?lsFuses=Calendar/Date&sDate=' + nMonth + '-' + dTarget.getDate() + '-' + dTarget.getFullYear() ;
		}
		
	}
	
	
//------------------------------------------------------------------------------------------------------------

	this.fRefreshDisplay	= function() {
		// Change Month Header
		if (this.divMonthHeader) {
			this.divMonthHeader.innerHTML = this.fsMonthAsString(this.stDisplay.nCurrMonth) + " " + this.stDisplay.nCurrYear;
		}

		// Redraw Date Cells
		this.fDrawCells();

		if ((this.stDisplay.nCurrMonth == this.dToday.getMonth() + 1) 
				&& (typeof this.stDisplay.dSelected == 'undefined')) {
			// If we are in Today's month and dSelected is unknown
			this.fDateDetail(0);

		} else if ((typeof this.stDisplay.dSelected == 'object') 
					&& (this.stDisplay.nCurrMonth == this.stDisplay.dSelected.getMonth() + 1)) {
			// If a date is selected and its in the currently displayed month
			
			this.fDateDetail(this.fnGetCellNumberFromDate(this.stDisplay.dSelected));
		}
		
	}
	
//------------------------------------------------------------------------------------------------------------

	this.fShowEventDetail	= function(nEventCnt) {
		var sMonthYearKey = this.fsMonthYearKey();
		var stMonthData = this.stMonthData[sMonthYearKey];
		var stEvent = this.stMonthData[sMonthYearKey].astEvents[nEventCnt];
		
		var sContent = '';
		var sTimePart = '';
		if (!stEvent.BALLDAY) {
			sTimePart = stEvent.STIMESTART;

			if (!stEvent.BNOENDTIME) {
				sTimePart += ' to ' + stEvent.STIMEEND;
			}
		}
		

		sContent += '<b>' + stEvent.STITLE + '</b><br>';
		sContent += '<p>' + this.fsDateLine(stEvent) + '</p><p>';
		if (stEvent.SLOCATION != ''){
			sContent += 'Location: ' + stEvent.SLOCATION + '.';
		}
		sContent += '  Click for More Information</p>';
		
		
		this.fWriteToDetails(sContent);
	}

//------------------------------------------------------------------------------------------------------------
	this.fsDateLine = function(stEvent, sFormat) {
		sContent = '';

		if (stEvent.BALLDAY == 'true') {
			sContent += 'All Day';
		} else if (stEvent.BNOENDTIME == 'true' || sFormat == 'short') {
			sContent += stEvent.STIMESTART;
		} else {
			sContent += stEvent.STIMESTART + ' - ' + stEvent.STIMEEND;
		}
		
		
		return sContent;
		
	}

//------------------------------------------------------------------------------------------------------------
	this.fDateDetail = function(nCell, eMouseEvent) {
		// get Data for this Month -------------
		if (!this.bDataLoaded) {
			return false;	
		}
		var sMonthYearKey = this.fsMonthYearKey();
		var stMonthData = this.stMonthData[sMonthYearKey];
		var astEvents = this.stMonthData[sMonthYearKey].astEvents;
		var dTarget 	= this.fdGetDateFromCellNumber(nCell);
		
		var bEventFound = false;
		if (dTarget != 0) {
			// Make sure we are referencing a valid cell
			if ((nCell <= 0) || (nCell > 42)) {
				nCell = 	this.fnGetCellNumberFromDate(this.stDisplay.dSelected);
			}
			
	
			//-------------------------------------------------------------------------------------------------
			// Highlight the Selected Cell 
			this.fSelectCell(nCell);
	
			//-------------------------------------------------------------------------------------------------
			// loop over the stMonthData to find if there is an event today
			var sContent = '<b>' + this.fsMonthAsString(dTarget.getMonth() + 1) + ' ' + dTarget.getDate() + ', ' + dTarget.getFullYear() + '</b><ul>';
			for (nCnt = 0; nCnt < astEvents.length; nCnt++) {
				if (astEvents[nCnt].NDAYNUM == dTarget.getDate()) {
					bEventFound = true;
					if (astEvents[nCnt].SCATEGORY != null) { sThisClass = 'Cal_Detail_General' }
						else { Object.dpDump(astEvents[nCnt].SCATEGORY);  sThisClass = 'Cal_Detail_' + astEvents[nCnt].SCATEGORY; }
					// Create the Link for the Event
					//sLink = '<a href="/index.cfm?lsFuses=department/' + astEvents[nCnt].SDEPSHORTCUT + '/' + astEvents[nCnt].NCONTENTID + '">' + astEvents[nCnt].STITLE + '</a>';

					//sLink = astEvents[nCnt].STITLE;

					sLink = astEvents[nCnt].STITLE;

					sContent += '<li class="' + sThisClass + '"><strong>' + this.fsDateLine(astEvents[nCnt], "short") + '</strong> - ' + sLink + "</li>";
				}
			}
			sContent += "</ul>";
	
			//this.divDetailOn.innerHTML = sContent;
			this.fWriteToDetails(sContent);
			this.fMoveDetailsBox(eMouseEvent);
			
		}
	}

//-------------------------------------------------------------------------------------------------	
	this.fHideDetailsBox		= function() {
		this.divDetailOn.style.display 	= 'none';
	}

//-------------------------------------------------------------------------------------------------	
	this.fMoveDetailsBox		= function(eMouseEvent) {
		var nWidth = 200;
		var nHeight = 100;
		var bShowDetails = false;
		
		
		nScrollTop	= 0;
		nScrollLeft	= 0;
		sScrollMode = 'unknown: ';
		if (document.documentElement.scrollTop || document.documentElement.scrollLeft) {
			nScrollTop	= document.documentElement.scrollTop;
			nScrollLeft	= document.documentElement.scrollLeft;
			sScrollMode = 'Document Scroll: ';
		} else if ( document.body.scrollTop || document.body.scrollLeft ) {
			nScrollTop	= document.body.scrollTop;
			nScrollLeft	= document.body.scrollLeft;
			sScrollMode = 'Body Scroll: ';
		}

		
		nMouseX = 0;
		nMouseY = 0;
		sBrowserMode = '?? Mouse: ';
		if (typeof(eMouseEvent) != 'undefined') {
			is.ns = false;
			is.ie = false;
			
			if (eMouseEvent.pageX != undefined) {
				is.ns = true;
			} else if (eMouseEvent.x != undefined) {
				is.ie = true;
			}
		
			if (is.ns) {
				sBrowserMode = 'NS Mouse: ';
				if (eMouseEvent.pageX > 0) {
					nMouseX = eMouseEvent.pageX;
					nMouseY = eMouseEvent.pageY;
					//nMouseX -= nScrollLeft;
					//nMouseY -= nScrollTop;
				}
			} else if (is.ie) {
				sBrowserMode = 'IE Mouse: ';
				nMouseX = eMouseEvent.x + nScrollLeft;
				nMouseY = eMouseEvent.y + nScrollTop;
			}
			//alert(sBrowserMode);
			bShowDetails = true;
			
		} else if (typeof(event) != 'undefined') {
			nMouseX = event.x + nScrollLeft;
			nMouseY = event.y + nScrollTop;
			bShowDetails = true;
		}

		//alert(eMouseEvent.pageX +': '+ nMouseX +', '+ nMouseY);

		//document.getElementById(sDivName + '_Debug').innerHTML = sScrollMode + nScrollLeft + ', ' + nScrollTop + '<br />';
		//document.getElementById(sDivName + '_Debug').innerHTML += sBrowserMode + nMouseX + ', ' + nMouseY + '<br />';
		
		if (bShowDetails) {
			/// Make sure we're not going off the screen with this
			/*
			if ((nMouseX + nWidth) > document.body.scrollWidth) nMouseX = nMouseX - (nMouseX + nWidth - document.body.scrollWidth);
			if ((nMouseY + nHeight) > document.body.scrollHeight) nMouseY = nMouseY - (nMouseY + nHeight - document.body.scrollHeight);
			*/
			
			this.divDetailOn.style.display 	= 'inline';
			this.divDetailOn.style.position	= 'absolute';
			
			nNewLeft = nMouseX - nWidth - 15;
			this.divDetailOn.style.left 	= nNewLeft + "px";
			
			nNewTop = nMouseY + 5;
			this.divDetailOn.style.top 		= nNewTop + "px";


			this.divDetailOn.style.width 	= nWidth;
			this.divDetailOn.style.height 	= nHeight;
			window.status = document.documentElement.scrollTop;

			//window.status = 'x:' + nMouseX + ' y:' + this.divDetailOn.style.top;
		} else {
			this.divDetailOn.style.display 	= 'none';
		}
	}


//-------------------------------------------------------------------------------------------------	
	this.fWriteToDetails		= function(sContent, bAppend) {
		if ((typeof bAppend == 'boolean') && (bAppend)) sContent = this.divDetailOn.innerHTML + '\n' + sContent;
		this.divDetailOn.innerHTML = sContent + '';
		
	}

	
	
	
	


//-------------------------------------------------------------------------------------------------	
//-------------------------------------------------------------------------------------------------	
// LOGIC Related Methods
//-------------------------------------------------------------------------------------------------	
	this.fsMonthYearKey		= function(nMonth, nYear) {
		if (typeof nMonth	== 'undefined')  nMonth = this.stDisplay.nCurrMonth;
		if (typeof nYear 	== 'undefined')  nYear = this.stDisplay.nCurrYear;
			
		return 	nMonth + '/' + nYear
	}


//------------------------------------------------------------------------------------------------------------
	this.fdGetDateFromCellNumber = function(nCellNumber) {

		var nDateOffset = -this.stDisplay.nFirstDayOfWeekOfMonth;
		var nDayPart = nDateOffset + nCellNumber;
		var dNew = new Date();
		if ((nDayPart > 0) && (nDayPart <= this.stDisplay.nDaysInMonth)) {
			dNew = new Date(this.stDisplay.nCurrYear, this.stDisplay.nCurrMonth - 1, nDayPart);
		} else if (nCellNumber != 0) {
			dNew = 0;	
		}

		return dNew;
	}
	

//------------------------------------------------------------------------------------------------------------
	this.fnGetCellNumberFromDate = function(dDate) {
		var nDateOffset = this.stDisplay.nFirstDayOfWeekOfMonth;
		var nCellNum = nDateOffset + dDate.getDate();
		return nCellNum;
	}
	

//------------------------------------------------------------------------------------------------------------

	this.fsMonthAsString 	= function(nMonth) {
		var asMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']

		if (nMonth && nMonth >= 1 && nMonth <= 12)	return asMonths[nMonth - 1]
		else return 'Unknown';
	}

//-------------------------------------------------------------------------------------------------	
	this.fComputeMonthInfo	= function() {
		this.stDisplay.nFirstDayOfMonth 		= new Date(this.stDisplay.nCurrYear, this.stDisplay.nCurrMonth - 1, 1);
		this.stDisplay.nFirstDayOfWeekOfMonth 	= this.stDisplay.nFirstDayOfMonth.getDay();
		this.stDisplay.nDaysInMonth 			= this.fnDaysInMonth();
	}

//------------------------------------------------------------------------------------------------------------

	this.fnDaysInMonth		= function(nMonth, nYear) {
		if (!nMonth) 	nMonth = this.stDisplay.nCurrMonth;
		if (!nYear) 	nYear = this.stDisplay.nCurrYear;
		
		var nDaysInMonth = 31;

		if (nMonth == 4 || nMonth == 6 || nMonth == 9 || nMonth == 11) nDaysInMonth = 30;
		if (nMonth == 2 && (nYear/4) != Math.floor(nYear/4))	nDaysInMonth = 28;
		if (nMonth == 2 && (nYear/4) == Math.floor(nYear/4))	nDaysInMonth = 29;
		return nDaysInMonth;
	}
	




//-------------------------------------------------------------------------------------------------	
//-------------------------------------------------------------------------------------------------	
// CONSTRUCTOR
//-------------------------------------------------------------------------------------------------	
	this.fComputeMonthInfo();
	this.stDisplay.nSelectedCell = this.fnGetCellNumberFromDate(this.stDisplay.dSelected);
	this.fAJAXCall();
	
	// If we've made it this far, we can display this calendar
	//this.divMaster.style.display = 'block';

}


