/*
	renderCalendar &#169;2008 Plymouth City Council
	
	INSTRUCTIONS
	Reference this file from HTML source, e.g...
		<script type="text/javascript" src="renderCalendar.js"></script>
	
	Set the [pcc.calendar.start] and [pcc.calendar.end] properties to be valid Javascript date objects
	(the code will accept any day within the month and will draw a calendar for the whole month).
	
	Optionally, set the [pcc.calendar.startWeekA] property to a Javascript date object.  This indicates
	when "WeekA" starts and the software will toggle WeekA and WeekB automatically from there.
	
	Call the [pcc.calendar.render()] method, passing a function used to render the date string itself.
	The function should accept a date as its first parameter and return a string representation of the date.
	Two examples follow...
	
		function(date) {return date.getDate();}
		function(date) {return '<a href="eventsList.asp?date=' + date.getFullYear() + '-' + date.getMonth() + 1 + '-' + date.getDate() + '">Show Events</a>';}
	
	The first function simply returns the date as a string, whilst the second constructs a hyperlink to a
	specific events page.
	
	The [pcc.calendar.render()] method returns the calendars as an HTML string that needs to be written to the browser.
	Each calendar appears in its own [div.calendar] element and all styling is applied via a stylesheet.
*/
var pcc = {
	calendar: {
		months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
		startWeekA: null,
		start: null,
		end: null,
		render: function(fnRender) {
			function renderHeader(date, months) {
				return '<thead>' +
					   '<tr class="month"><th colspan="7">' + months[date.getMonth()] + ' ' + date.getFullYear() + '</th></tr>' + 
					   '<tr class="days"><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th>' + 
					   '</thead>';
			}
			function renderBody(date, weekA, fnWrite) {
				function renderDate(val) {
					var html = '';
					var isPadding = (val == null);
					// Write the new row...
					if (!(iCell % 7)) {
						var className = ((isPadding && iCell > 0) ? 'padding' : ((iCell % 2) ? 'calEven' : 'calOdd') + ' ' + weekFlag);
						weekFlag = ((weekFlag == 'weekA') ? 'weekB' : 'weekA');
						if (iCell > 0) html += '</tr>';
						html += '<tr class="' + className + '">';
					}
					// Write the data...
					html += '<td' + (isPadding ? ' class="padding"' : '') + '>' + (isPadding ? '&nbsp;' : val) + '</td>';
					// Increment the Cell Counter...
					iCell++
					// Return the results...
					return html;
				}
				// Get the start of the month...
				var som = new Date(date);
				som.setDate(1);
				// Get the start of the first week (and the initial padding)...
				var sow = new Date(som);
				var iPadding = (sow.getDay() + 6) % 7;
				sow.setDate(sow.getDate() - iPadding)
				// Is the first week WeekA or WeekB..?
				var msWeek = 1000 * 60 * 60 * 24 * 7;
				var dWeeks = Math.round(((sow - weekA) / msWeek));
				var weekFlag = (dWeeks % 2) ? 'weekB' : 'weekA';
				// Write the calendar...
				var iCell = 0;
				var html = '';
				var now = new Date(som);
				// Write the padding at the start...
				for (var i = 0; i < iPadding; i++) {html += renderDate(null);}
				// Write the rest of the month...
				while (now.getMonth() == som.getMonth()) {
					html += renderDate(fnWrite(now));
					now.setDate(now.getDate() + 1);
				}
				// Write the padding at the end...
				var noCells = 6 * 7; // 7 days-a-week, 6 weeks.
				for (var i = iCell; i < noCells; i++) {html += renderDate(null);}
				// Return the results...
				return '<tbody>' + html + '</tbody>';
			}
			// Remember the months that we want...
			if (this.start < this.end) {
				var dates = []; // Empty Array
				var date = new Date(this.start)
				date.setDate(1); // Reset to the 1st of the month
				// Step through, month-by-month, adding to the dates[] array until we've passed the end month...
				for (null; date <= this.end; date.setMonth(date.getMonth() + 1)) {dates.push(new Date(date));}
			}
			// For each month, write out a calendar DIV...
			var html = '';
			for (var i = 0; i < dates.length; i++) {
				var date = dates[i]
				html += '<div class="calendar"><table>' +
						renderHeader(date, this.months) +
						renderBody(date, this.startWeekA, fnRender) + 
						'</table></div>';
			}
			return html;
		}
	}
};

