/*
 * Copyrighted by Paul Saunders, 2008, http://psaunders.net.
 *
 * Redistribution and use of any content in source and/or binary forms,
 * with or without modification, are not permitted.
 *
 * The content of this web site and the software herein is provided by the
 * copyright holders and contributors "as is" and any express or implied
 * warranties, including, but not limited to, the implied warranties of
 * merchantability and fitness for a particular purpose are disclaimed.
 * In no event shall the copyright owner or contributors be liable for any
 * direct, indirect, incidental, special, exemplary, or consequential damages
 * (including, but not limited to, procurement of substitute goods or services;
 * loss of use, data, or profits; or business interruption) however caused and
 * on any theory of liability, whether in contract, strict liability, or tort
 * (including negligence or otherwise) arising in any way out of the use of
 * this software, even if advised of the possibility of such damage.
*/
var noEventMsg =  'No events for ';
var eventMsg = 'Events for ';
var months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
var days = ['S','M','T','W','Th','F','Sa'];
var todaysDate = new Date();
// Array to store calendar event objects
var calArray = new Array();
//HTML strings used to construct the calendar
var calId = 'calendar';
var calEventId = 'calendar_event';
var startDiv = '<div>';
var endDiv = '<\/div>';
var startUl = '<ul>';
var endUl = '<\/ul>'
var startLi = '<li>';
var endLi = '<\/li>'
var endSpan = '<\/span>';
var nbsp = '&nbsp;'
var brTag = '<br>';
var endAnchor = '<\/a>';
var brX3 = brTag+nbsp+brTag+nbsp+brTag+nbsp;
var calBodyStart = '<div id="calendar_body">';
var calEventStart = '<div id="calendar_event">';
var calHeaderStart = '<div id="calendar_header">';
var calDaysStart = '<span class="calendar_day">';
var startCalRow = '<div class="calendar_row">';
var endCalRow = endDiv;
var calNumStart = '<span class="calendar_num">';
var calNumStartEvent = '<span class="calendar_num calendar_inevt">';
var emptyCalBox = '<span class="calendar_box empty_box">' + endSpan;
var calInEventStart = '<span class="calendar_inevt">';
var startCalNav = '<div id="calendar_nav">';
var calNavClickStart = '<a href="#" onclick="return navigateCalendar(';
var calNavClickEnd = ');">';
var calNavToday = '<a href="#" onclick="start(); return false;">Today</a>';
var calBodyId = 'calendar_body';
var calBoxClass = 'calendar_box';
var selDayClass = 'day_sel';
var dbcntr = 0;
var prevDay = "0";

function start() {
    // Display the calendar by creating the HTML and putting it into the div
    document.getElementById(calId).innerHTML = 
    	calBodyStart + renderCalendarHTML(0,0) + endDiv + calEventStart + endDiv;
    // Display today's event descriptions, if any found...
    showEvents(todaysDate.getDate(), todaysDate.getMonth(), todaysDate.getFullYear());
}

function navigateCalendar(yy, mm) {
	if (cala = renderCalendarHTML(yy,mm)) {
		document.getElementById(calBodyId).innerHTML = cala;
	}
	return false;
}

function AddEvent(dateString, dayString, eventString, description, beginDateString, endDateString) {
	// Create CalEvent objects and put them into an array
	var CalEvent = {
		date : dateString || "",
		day : dayString || "",
		eventText : eventString || "",
		desc : description || "",
		beginDate : beginDateString || "",
		endDate : endDateString || ""
	}
	calArray[calArray.length] = CalEvent;
}

function showCalArray() {
	var displayMsg;
    for (x = 0; x < calArray.length; x++) {
    	displayMsg=displayMsg+calArray[x].date + " " + calArray[x].eventText + ",";
    }
    alert(displayMsg);
}

function renderCalendarHTML(yy, mm) {
    // Create a date object
	var calendar = new Date();
    // Set the date to the first day of the month
    calendar.setDate(1);
    // If first time in, year and month will be zero (we will use today's date)
    if (yy > 0 || mm > 0) {
    	// Set the date to the requested year and month
	    calendar.setFullYear(yy);
	    calendar.setMonth(mm);
    }
    var curYear = calendar.getFullYear();
    var curMonth = calendar.getMonth();
    var weekday = calendar.getDay();
    // Create the output HTML and put the month header into it
    var calHTML = startDiv + calHeaderStart + months[curMonth]  + ' ' + curYear + endDiv;
    // Create the calendar days header row
    calHTML += startCalRow;
    for (dayCntr=0; dayCntr < 7; dayCntr++) {
    	calHTML += calDaysStart + days[dayCntr] + endSpan;
    }
    calHTML += endCalRow;
    var dayOfWeek = calendar.getDay();
    var daysInMonth = new Date(curYear, curMonth + 1, 0).getDate();
    // Create empty boxes until we get to the first day of the month
    calHTML += startCalRow;
    for (dayCntr=0; dayCntr < weekday; dayCntr++) {
    	calHTML += emptyCalBox;
    }
    // Now we start filling in the calendar with real data...
    var monthsDate = new Date(curYear, curMonth, 1);
    var rowCount = 1;
    var rowInd = 'first';
    for (dayCntr=1; dayCntr <= daysInMonth; dayCntr++) {
        if (weekday == 7) {
        	calHTML += endCalRow + startCalRow;
            weekday = 0;
            rowCount++;
        }
        // Set the date to the proper day in the month
        monthsDate.setDate(dayCntr);
        // If this date is today's date, we decorate the calendar box...
        var isToday = false;
        if (todaysDate.getFullYear() == monthsDate.getFullYear()
       	 && todaysDate.getMonth() == monthsDate.getMonth()
       	 && todaysDate.getDate() == monthsDate.getDate()) {
        	isToday = true;
        }
        calHTML += '<span ' 
        	+ renderDateLinks(monthsDate.getDate(), monthsDate.getMonth(), monthsDate.getFullYear(), isToday) 
        	+ '>';
        if (getCalEvents(monthsDate.getDate(), monthsDate.getMonth(), monthsDate.getFullYear()) == brX3) {
        	calHTML += calNumStart;
        }else {
        	calHTML += calNumStartEvent; 
        }
        calHTML += dayCntr  + endSpan + endSpan;
        weekday++;
    } // end for loop
    // Finish row with blank calendar boxes...
    for (dayCntr=weekday; dayCntr < 7; dayCntr++) {
    	calHTML += emptyCalBox;
    }
    // Add blank rows for those months that use 4 or 5 rows...
    while (rowCount < 6) {
    	calHTML += endCalRow + startCalRow;
        for(dex=1; dex <= 7; dex++) {
        	calHTML += emptyCalBox;
        }
        rowCount++;
    }
    calHTML += endDiv;
    // Finally create the navigation links at the bottom of the calendar...
    calHTML += endDiv + createCalNav(calendar);
    return calHTML;
}

function createCalNav(calendar) {
    // This part is tricky only because if the month is Decmeber or January
    // we have to manually set the next / prev month and adjust the current year.
    var curYear = calendar.getFullYear();
    var curMonth = calendar.getMonth();
	var prevYear = curYear - 1;
	var prevMonth;
	var nextYear = curYear + 1;
	var nextMonth;
	// Set the next and prev year links...
	var prevYearCurMonthLink = prevYear + ',' + curMonth;
	var nextYearCurMonthLink = nextYear + ',' + curMonth;
	// Set the next and prev months...
	if (calendar.getMonth() == 0) {
		prevMonth = 11;
		curYear--;
	}else { 
		prevMonth = calendar.getMonth() - 1;
	}
	var curYearPrevMonth = curYear + ',' + prevMonth;
	// Reset year, in case we changed it above
	curYear = calendar.getFullYear();
	if (calendar.getMonth() == 11) {
		nextMonth = 0;
		curYear++;
	}else {
		nextMonth = calendar.getMonth() + 1;
	}
	var curYearNextMonth = curYear + ',' + nextMonth;
    return startCalNav 
    + calNavClickStart + prevYearCurMonthLink + calNavClickEnd +'<<' + endAnchor 
    + nbsp + nbsp + nbsp + nbsp  
    + calNavClickStart + curYearPrevMonth + calNavClickEnd + '<' + endAnchor 
    + nbsp + nbsp + nbsp + nbsp 
    + calNavToday 
    + nbsp + nbsp + nbsp + nbsp 
    + calNavClickStart + curYearNextMonth + calNavClickEnd + '>' + endAnchor 
    + nbsp + nbsp + nbsp + nbsp 
    + calNavClickStart + nextYearCurMonthLink + calNavClickEnd + '>>' + endAnchor 
    + endDiv;
}

function renderDateLinks(day, month, year, isToday) {
    return 'id="' + day + '" class="' + calBoxClass 
         + '" onclick="showEvents(' + day + ',' + month + ',' + year 
         + '); return false;"';
}

function showEvents(day, month, year) {
    var eventMessage = '';
    var date = new Date(year, month, day);
    var dayOfWeek = days[date.getDay()];
    var eventString = getEventDescriptions(day, (month+1), year, dayOfWeek);
    var dateString = months[month] + ' ' + day + ', ' + year;
    if (eventString == '') {
        eventMessage += noEventMsg + dateString + brX3;
    }else {
        eventMessage += eventMsg + dateString + ':' + startUl + eventString + endUl;
    }
    if (document.getElementById(calEventId)) {
        document.getElementById(calEventId).innerHTML = brTag + brTag + eventMessage;
    }
    if (document.getElementById(prevDay)) {
    	var className = document.getElementById(prevDay).className;
    	if (className.indexOf(selDayClass) > 0) {
    		className = className.substring(0,className.indexOf(selDayClass)-1);
    	}
    	document.getElementById(prevDay).className = className;
    }
    if (document.getElementById(day)) {
    	var className = document.getElementById(day).className;
    	document.getElementById(day).className = className + ' ' + selDayClass;
    	prevDay = day;
    }
    return eventMessage;
}

function getCalEvents(day, month, year) {
    var eventMessage = '';
    var date = new Date(year, month, day);
    var dayOfWeek = days[date.getDay()];
    var eventString = getEventsForDate(day, (month+1), year, dayOfWeek);
    if (eventString == '') {
        eventMessage = brX3;
    }else {
        eventMessage = calInEventStart + eventString + endSpan;
    }
    return eventMessage;
}

function getEventsForDate(dayVal, monthVal, yearVal, dayOfWeek) {
	var eventString = ""; 
	// Make sure month and day have leading zeros 
	// Note, adding the empty string makes the compares below to work 
	monthVal = (monthVal > 9 ? monthVal + "" : "0" + monthVal);
	dayVal = (dayVal > 9 ? dayVal + "" : "0" + dayVal);
	var eventCntr = 0;
    for (x = 0; x < calArray.length; x++) {
    	if (calArray[x].date == (yearVal + "" + monthVal + "" + dayVal)) {
    		eventString += brTag + calArray[x].eventText;
    		++eventCntr;
    	}else if (calArray[x].date == ("0000" + monthVal + "" + dayVal)) {
    		eventString += brTag + calArray[x].eventText;
    		++eventCntr;
    	}else {
    		var date = new Date(yearVal, monthVal-1, dayVal);
    		var beginDate = createDate(calArray[x].beginDate);
    		var endDate = createDate(calArray[x].endDate);
    		if (calArray[x].day == dayOfWeek && ((beginDate == null && endDate == null) || (date >= beginDate && date <= endDate))) {
	    		eventString += brTag + calArray[x].eventText;
	    		++eventCntr;
    		}
    	}
    	// Limit the number of events showing in calendar to 4
    	if (eventCntr > 4) {
    		break;
    	}
    }
    return eventString;
}

function getEventDescriptions(dayVal, monthVal, yearVal, dayOfWeek) {
	var eventString = ""; 
	// Make sure month and day have leading zeros 
	// Note, adding the empty string makes the compares below to work 
	monthVal = (monthVal > 9 ? monthVal + "" : "0" + monthVal);
	dayVal = (dayVal > 9 ? dayVal + "" : "0" + dayVal);
    for (x = 0; x < calArray.length; x++) {
    	if (calArray[x].date == (yearVal + monthVal + dayVal)) {
    		eventString += startLi + calArray[x].desc + endLi;
    	}else if (calArray[x].date == ("0000" + monthVal + dayVal)) {
    		eventString += startLi + calArray[x].desc + endLi;
    	}else {
    		var date = new Date(yearVal, monthVal-1, dayVal);
    		var beginDate = createDate(calArray[x].beginDate);
    		var endDate = createDate(calArray[x].endDate);
    		if (calArray[x].day == dayOfWeek && ((beginDate == null && endDate == null) || (date >= beginDate && date <= endDate))) {
	    		eventString += startLi + calArray[x].desc + endLi;
    		}
    	}
    }
    return eventString;
}

function createDate(dateString) {
	if (dateString == "") {
		return null;
	}
	var year = dateString.substring(0,4);
	var month = dateString.substring(4,6);
	var day = dateString.substring(6,8);
	return new Date(year, month-1, day);
}