jQuery(function($) {

	$.extend({

		// function dateObject( timestamp )
		// 
		// Returns object containing human-readable information about the date
		// Params:
		//      timestamp: Unix-formatted timestamp of date

		dateObject : function( timestamp ) {
			var theTime = ( !!timestamp ) ? timestamp : parseInt(new Date().getTime().toString().substring(0, 10));
			var d = new Object;
			d.timestamp = new Date( theTime*1000 );
			d.year = d.timestamp.getUTCFullYear();
			d.month = d.timestamp.getUTCMonth();
			d.date = d.timestamp.getUTCDate();
			d.day = d.timestamp.getUTCDay();
			return d;
			delete d;
		},
		
		// function daysInMonth( month, year )
		// 
		// Returns number of days in given month and year
		// Credit: Matt Billings (http://www.mattbillings.com)
		// Params:
		//      month: zero-indexed numeric representation of month (e.g. March = 2)
		//      year: 4-digit numeric representation of year
		
		daysInMonth : function( month, year ){
			return ( 32-new Date( year, month, 32 ).getDate() );
		},

		// function firstDayOfMonth( month, year )
		// 
		// Returns zero-indexed numeric representation of the first day of given month and year
		// Params:
		//      month: zero-indexed numeric representation of month (e.g. March = 2)
		//      year: 4-digit numeric representation of year

		firstDayOfMonth : function( month, year ){
			return new Date( settings.months[month] + ' 1, ' + year ).getUTCDay();
		},

		// function generatePagination( month, year )
		// 
		// Returns object containing information used to page through next/previous month
		// Params:
		//      month: zero-indexed numeric representation of month (e.g. March = 2)
		//      year: 4-digit numeric representation of year

		generatePagination: function( month, year ){
			var pagination = new Object;
			pagination.prevMonth = ( month-1 < 0 ) ? 11 : month-1;
			pagination.prevMonthYear = ( month-1 < 0 ) ? year-1 : year;
			pagination.nextMonth = ( month+1 < 12 ) ? month+1 : 0;
			pagination.nextMonthYear = ( month+1 < 12 ) ? year : year+1;
			return pagination;
			delete pagination;
		},

		// function generateMonth( month, year, calID, events )
		// 
		// Returns string containing HTML for the calendar of given month, year on calID with events
		// Params:
		//      month: zero-indexed numeric representation of month (e.g. March = 2)
		//      year: 4-digit numeric representation of year
		//      calID: Zero-indexed ID of given calendar
		//      events: Array containing JSON-imported events to be parsed through

		generateMonth: function( month, year, calID, events ) {
			var day = 0;
			var date = 0;
			var toReturn = '<div id="' + calID + '" class="' + settings.classPrefix + '" rel="generated">';
				toReturn += '<p class="' + settings.classPrefix + '-month">' + settings.months[month] + ' ' + year + '</p>';
				toReturn += '<ul class="' + settings.classPrefix + '-controls">';
					toReturn += '<li class="' + settings.classPrefix + '-prev"><a href="#">Previous Month</a></li>';
					toReturn += '<li class="' + settings.classPrefix + '-next"><a href="#">Next Month</a></li>';
				toReturn += '</ul>';
				toReturn += '<div class="' + settings.classPrefix + '-cal">';
					toReturn += '<table cellspacing="0" cellpadding="0" border="1">';
						toReturn += '<thead>';
							for(i=0;i<settings.daysShort.length;i++)
								toReturn +=  '<td>' + settings.daysShort[i] +'</td>';
						toReturn += '</thead>';
						toReturn += '<tbody>';
							toReturn += '<tr>';
								for(i=0;i<$.firstDayOfMonth( month, year );i++){
									toReturn += '<td class="' + settings.classPrefix + '-empty"></td>';
									day++;
									if( ((day)/7) == Math.round((day)/7) )
										toReturn += '</tr><tr>';
								}
								for( i=0; i<$.daysInMonth( month, year ); i++ ){
									var content = '';
									var startDay = Date.UTC( year, month, (i+1), 0, 0, 0, 0 )/1000;
									var endDay = Date.UTC( year, month, (i+1), 23, 59, 59, 999 )/1000;
									for( j=0; j<events.length; j++ ){										
										if( ( ( events[j]['@start'] > startDay ) && ( events[j]['@start'] < endDay ) ) || ( ( events[j]['@end'] > startDay ) && ( events[j]['@end'] < endDay ) ) || ( ( events[j]['@start'] > startDay ) && ( events[j]['@end'] < endDay ) ) || ( ( events[j]['@start'] < startDay ) && ( events[j]['@end'] > endDay ) ) ){
											content += '<div class="' + settings.classPrefix + '-eventt">' + events[j]['#popup'] + '</div>';
										}
									}
									toReturn += '<td';
									if( content != '' )
										toReturn += ' class="' + settings.classPrefix + '-hasevent"';
									toReturn += '><span><a href="" class="' + settings.classPrefix + '-open">' + (i+1) + '</a><div class="' + settings.classPrefix + '-popup"><h3>' + settings.months[month] + ' ' + (i+1) + ', ' + year + '</h3><a href="#" class="close">Close</a><ul class="popupbody">' + content + '</ul></div></span></td>';
									day++;
									if( ((day)/7) == Math.round((day)/7) ){
										toReturn += '</tr>';
										if( day < $.daysInMonth( month, year ) )
											toReturn += '<tr>';
									}
									delete content;
								}
								while( day % 7 != 0 ){
									toReturn += '<td class="' + settings.classPrefix + '-empty"></td>';
									day++;
								}
							toReturn += '</tr>';
						toReturn += '</tbody>';
					toReturn += '</table>';
				toReturn += '</div>';			
			toReturn += '</div>';
			toReturn += '';
			return toReturn;
			delete toReturn;
			delete day;
			delete date;
		}
	});

	$.fn.eventCalendar = function( src, options ) {

		settings = jQuery.extend({
			method: 'replace',
			months: ['January','February','March','April','May','June','July','August','September','October','November','December'],
			days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
			daysShort: ['S','M','T','W','T','F','S'],
			classPrefix: 'eventcalendar'
		}, options);
		
		var calIDNum = 1;
		var calID = settings.classPrefix + calIDNum;
		

		return this.each(function(){
			
			var now = $.dateObject();
			var events = new Array;
			$.ajax({
				async: false,
				success: function (data, textStatus) {
					for( i=0; i<data.event.length; i++ ){
						events.push( data.event[i] );
					}
				},
				dataType: "json",
				url: src
			});

			$(this).html( $.generateMonth( now.month, now.year, calID, events ) );
			$(this).data('popup_h', (-($(this).height()-2))+"px");

			var pagination = $.generatePagination( now.month, now.year );
			$( '#' + calID + ' .' + settings.classPrefix + '-prev > a' ).live('click',function(e){
				e.preventDefault();
				var innerWrap = $(this).closest( '.' + settings.classPrefix )
				var wrap = innerWrap.parent();
				var thisCalID = innerWrap.attr('id');
				wrap.html( $.generateMonth( pagination.prevMonth, pagination.prevMonthYear, thisCalID, events ) );
				pagination = $.generatePagination( pagination.prevMonth, pagination.prevMonthYear );
				delete innerWrap;
				delete thisCalID;
				delete innerWrap;
			});

			$( '#' + calID + ' .'+settings.classPrefix+'-next > a' ).live('click',function(e){
				e.preventDefault();
				var innerWrap = $(this).closest( '.' + settings.classPrefix )
				var wrap = innerWrap.parent();
				var thisCalID = innerWrap.attr('id');
				wrap.html( $.generateMonth( pagination.nextMonth, pagination.nextMonthYear, thisCalID, events ) );
				pagination = $.generatePagination( pagination.nextMonth, pagination.nextMonthYear );
				delete innerWrap;
				delete thisCalID;
				delete innerWrap;
			});

			calIDNum++;
			calID = settings.classPrefix + calIDNum;

		});
	}

});