/*
* Ajax Calendar
*
* Created By: Matt Clarkson <matt@iws.co.nz> - 2006-09-07
*
*/

function ajaxCalendar(idContainer, showCat, showYear, showMonth, showDay) {

	this.container = $(idContainer);
	this.eventsContainer;

	// if we have a full date or none at all then just display the events for that date/current date, else display entire months
	this.dateSelected = false;

	if (typeof(showCat) == 'undefined') {
		this.category = 0;
	}
	else {
		this.category = parseInt(showCat, 10);

	}

	if (typeof(showYear) == 'undefined') {
		this.year = new Date().getFullYear();
		this.month = new Date().getMonth()+1;
		this.day = new Date().getDate();

		//this.dateSelected = true;
	}
	else {
		this.year = parseInt(showYear, 10);

		if (typeof(showMonth) == 'undefined') {
			this.month = 1;
			this.day = 1;
		}
		else {
			this.month = parseInt(showMonth, 10);

			if (typeof(showDay) == 'undefined') {
				this.day = 1;
			}
			else {
				this.day = parseInt(showDay, 10);

				this.dateSelected = true;
			}
		}
	}

	/*
	* dayId(date)
	*
	* id for given date
	*/
	this.dayId = function(date) {
		return 'calDay_'+date.getFullYear()+'_'+(date.getMonth()+1)+'_'+date.getDate();
	}

	this.selectedDate = new Date();
	this.selectedDate.setFullYear(this.year, this.month-1, this.day);

	this.idSelectedDay = null;

	if (this.dateSelected) {
		this.idSelectedDay = this.dayId(this.selectedDate);
	}

	this.days = new Array('Mon', 'Tues', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');
	this.longDays = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
	this.months = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
	this.daySuffix = new Array('st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'st');
	this.dateProvider = '/comp_calendar/data_provider.php';
	//this.eventPage = '/home.html';
  this.eventPage = '/9.html';

	this.thisDayEvents = new Array();

	this.myData = new Array;
	this.calDayDates = new Array();

	this.eventLargeContainer, this.eventLargeHeading, this.eventHolder;


	// hack: this is used so that call back functions access the correct instance of this object
	var me=this;


	/*
	* drawCalendar()
	*
	* creates and HTML calendar table
	*/
	this.drawCalendar = function() {

		var calTable = document.createElement('table');
		calTable.border=0;
		calTable.cellSpacing=0;
		calTable.align="center"


		if($('calTable')) {
			this.container.replaceChild(calTable, $('calTable'));
		}
		else {
			this.container.appendChild(calTable);
		}
		calTable.id = 'calTable';

		var calTHead = document.createElement('thead');
		calTable.appendChild(calTHead);

		var calTBody= document.createElement('tbody');
		calTable.appendChild(calTBody);

		var calRow = document.createElement('tr');
		calRow.id = 'calYearRow';
		calTHead.appendChild(calRow);

		// Display Date
		var calTd = document.createElement('th');
		calTd.innerHTML = '&lt;';
		calTd.id = 'calPrevMonth';
		calRow.appendChild(calTd);

		var calTd = document.createElement('th');
		calTd.colSpan=5;
		calTd.innerHTML = this.months[this.month-1]+' '+this.year;
		calRow.appendChild(calTd);

		var calTd = document.createElement('th');
		calTd.innerHTML = '&gt;';
		calTd.id = 'calNextMonth';
		calRow.appendChild(calTd);



		// Day Headers
		var calRow = document.createElement('tr');
		calRow.id = 'calDaysRow';
		calTHead.appendChild(calRow);

		for(var i=0;i<7;i++) {
			var calTd = document.createElement('th');
			calTd.innerHTML = this.days[i].substr(0, 1);
			calRow.appendChild(calTd);
		}

		// Days
		var startDate = new Date(this.year, this.month-1, '1');
		var thisDate = new Date();
		var offset = startDate.getDay();
		var j=0;

		do { // loop for each week until in next month

			calRow = document.createElement('tr');

			calRow.className = j % 2 ? 'calWeekOdd': 'calWeekEven';
			calTBody.appendChild(calRow);
			// Each day of the week
			for(var i=1;i<=7;i++) {

				thisDate = new Date(this.year, this.month-1, '1');
				thisDate.setDate(startDate.getDate()+((j*7+i)-offset));
				calTd = document.createElement('td');

				if (thisDate.getMonth()+1 == this.month) {
					calTd.className = 'calDay calDayActiveMonth';
				}
				else {
					calTd.className = 'calDay calDayInactiveMonth';
				}
				if (i == 7) {
					calTd.className =  calTd.className + ' end';
				}

				calRow.appendChild(calTd);

				calDiv = document.createElement('div');
				calDiv.innerHTML = thisDate.getDate();
				calTd.id = this.dayId(thisDate);
				this.calDayDates[calTd.id] = new Date(thisDate.getFullYear(), thisDate.getMonth(), thisDate.getDate());

				calTd.appendChild(calDiv);

				Event.observe(this.dayId(thisDate), 'click', this.calDayClick);
			}
			j++;

		}
		while(thisDate.getMonth() < this.month && thisDate.getFullYear() <= this.year );



		// Attach event listners
		Event.observe('calPrevMonth', 'click', this.previousMonth);
		Event.observe('calNextMonth', 'click', this.nextMonth);

		// Draw select box
		var selectBox = document.createElement('select');
		if ($('ajaxCalendarSelect')) {
			$(idContainer).replaceChild(selectBox, $('ajaxCalendarSelect'));
		}
		else {
			var selectBoxLabel = document.createElement('label');
			selectBoxLabel.setAttribute('for', 'ajaxCalendarSelect');
			selectBoxLabel.innerHTML = 'Search a different month:';

			$(idContainer).appendChild(selectBoxLabel);
			$(idContainer).appendChild(selectBox);
		}
		selectBox.id = 'ajaxCalendarSelect';
		Event.observe($('ajaxCalendarSelect'), 'change', function(e) {
			var elmVal = $('ajaxCalendarSelect').value;
			var time = elmVal.split('|');

			me.gotoMonthYear(parseInt(time[0])+1, parseInt(time[1]));
		});

		this.dateObj = new Date();
		this.selectMonth = this.dateObj.getMonth();
		this.selectYear = this.dateObj.getFullYear();

		var j = 0;

		var option = document.createElement('option')
		option.innerHTML = 'select month...';
		selectBox.appendChild(option);

		for (var i = 0; i < 12; i++) {	// We'll put 12 months in the select box
			var currMonth = this.months[(this.selectMonth + j)];

			var option = document.createElement('option');
			option.value = this.selectMonth + j + '|' + this.selectYear;
			option.innerHTML = currMonth + ' ' + this.selectYear;
				selectBox.appendChild(option);

			j++;
			if ((this.selectMonth + j) == 12) {
				this.selectMonth = 0;
				j = 0;

				this.selectYear = this.dateObj.getFullYear() + 1;
			}
		}

	} // this.create();


	/*
	* gotoMonth(offset)
	*
	* adds 'offset' months to the current month and updates calendar
	*/
	this.gotoMonth = function(offset) {

		var thisDate = new Date(this.year, this.month-1);
		var newDate = new Date(this.year, this.month-1);

		newDate.setMonth(thisDate.getMonth()+parseInt(offset));

		this.year = newDate.getFullYear();
		this.month = newDate.getMonth()+1;

		$$('#calEventsContainer .calEventDetail').each(function(i) {
			i.remove();
		});

		this.drawCalendar();
		this.getCalEvents();

	}

	/*
	* gotoMonthYear(month,year)
	*
	* goes to month and year and updates calendar
	*/
	this.gotoMonthYear = function(month, year) {
		window.location.replace(this.eventPage+'?c='+this.category+'&y='+year+'&m='+month);
	}



	/*
	* nextMonth()
	*
	* advances to the next month
	*/
	this.nextMonth = function() {
		//me.gotoMonth(+1);
		if (me.month == 12) {
			month = 1;
			year = me.year + 1;
		} else {
			month = me.month + 1;
			year = me.year;
		}
		me.gotoMonthYear(month, year);
	}



	/*
	* previousMonth()
	*
	* advances to the next month
	*/
	this.previousMonth = function() {
		//me.gotoMonth(-1);
		if (me.month == 1) {
			month = 12;
			year = me.year - 1;
		} else {
			month = me.month - 1;
			year = me.year;
		}
		me.gotoMonthYear(month, year);
	}




	/*
	* parseCalEvents
	*
	* This methodis an onSuccess AJAX callback from the getCalEvents method
	*/
	this.parseCalEvents = function(xml) {
		response = xml.responseXML;
		var calendars = response.getElementsByTagName('calendar');

		var dataIndex = 0;

		for(i=0;i<calendars.length;i++) {
			var calEvents = calendars[i].getElementsByTagName('event');
			var calendar_id = calendars[i].getAttribute('calendar_id');

			for(j=0;j<calEvents.length;j++) {

				var event_id = calEvents[j].getAttribute('event_id');
				var event_name = calEvents[j].getAttribute('event_name');
				var event_location = calEvents[j].getAttribute('location');
				var event_start_year = parseInt(calEvents[j].getAttribute('start_year'));
				var event_start_month= parseInt(calEvents[j].getAttribute('start_month'))-1;
				var event_start_day = parseInt(calEvents[j].getAttribute('start_day'));
				var event_start_time = calEvents[j].getAttribute('start_time');
				var event_end_year = parseInt(calEvents[j].getAttribute('end_year'));
				var event_end_month= parseInt(calEvents[j].getAttribute('end_month'))-1;
				var event_end_day = parseInt(calEvents[j].getAttribute('end_day'));
				var event_end_time = calEvents[j].getAttribute('end_time');
				var event_start_date = new Date(event_start_year, event_start_month, event_start_day, event_start_time.substr(0, 2), event_start_time.substr(3, 2));
				var event_end_date = new Date(event_end_year, event_end_month, event_end_day, event_end_time.substr(0, 2), event_end_time.substr(3, 2));
				var event_description = calEvents[j].getAttribute('description');


				me.myData[dataIndex++] = {calendar_id:calendar_id,
										  event_id: event_id,
										  event_name: event_name,
										  event_location: event_location,
										  event_start_date: event_start_date,
										  event_start_time: event_start_time,
										  event_end_date: event_end_date,
										  event_end_time: event_end_time,
										  event_description: event_description
										  };

			}
		}

		// Sort events
		me.myData.sort(me.sortByDate);


		if (!me.eventsContainer) {
			me.eventsContainer = document.createElement('div');
			me.eventsContainer.id = 'calEventsContainer';
			me.container.appendChild(me.eventsContainer);
		}

		if (!$('calEventsLabel')) {
			var label = document.createElement('div');
			label.id = 'calEventsLabel';
			label.innerHTML = '<b>Events:</b>';
			me.eventsContainer.appendChild(label);
		}

		if (!$('calComingEventsLabel')) {
			var hr = document.createElement('hr');
			me.container.appendChild(hr);

			var label = document.createElement('div');
			label.id = 'calComingEventsLabel';
			label.innerHTML = '<b>Coming Events:</b>';
			me.container.appendChild(label);
		}

		if ($('eventLargeContainerHome') && !$('eventLargeContainer')) {
			me.eventLargeContainer = document.createElement('div');
			me.eventLargeContainer.id = 'eventLargeContainer';
			me.eventLargeContainer.className = 'eventHolderContainer';

			me.eventLargeHeading = document.createElement('h2');
			me.eventLargeContainer.appendChild(me.eventLargeHeading);

			$('eventLargeContainerHome').appendChild(me.eventLargeContainer);
		}

		me.updateCalEvents();

		me.showEvents(me.selectedDate);

		if ($('eventLargeContainer')) {
			me.showEventsLarge(me.selectedDate);
		}

		me.showComingEvents();

	} // this.parseCalEvents();



	/*
	* updateCalEvents()
	*
	* Refresh the list of events
	*/
	this.updateCalEvents = function() {
		var days = new Object;

		for (i=0;i<me.myData.length;i++) {

			var tmp_date = new Date(me.myData[i].event_start_date);
			while (tmp_date.getFullYear() <= me.myData[i].event_end_date.getFullYear() &&
					tmp_date.getMonth() <= me.myData[i].event_end_date.getMonth() &&
					tmp_date.getDate() <= me.myData[i].event_end_date.getDate()) {


				if (isNaN(parseInt(days[this.dayId(tmp_date)]))) {
					days[this.dayId(tmp_date)] = 0;

				}


				days[this.dayId(tmp_date)]++;

				tmp_date.setDate(tmp_date.getDate()+1);
			}
		}

		// get Update calendar highlighting
		var hDays = document.getElementsByClassName('calDay');

		for(i=0;i<hDays.length;i++) {

			if(days[hDays[i].id] > 0) {
				hDays[i].className = hDays[i].className + ' calDayEvent';
			}
		}

		if (this.idSelectedDay)
			$(this.idSelectedDay).className = $(this.idSelectedDay).className + ' calDaySelected';
	}



	/*
	* showEvents(day)
	*
	* Refresh the list of events
	*/
	this.showEvents = function(day) {
		var totalEventsShown = 0;

		for (i=0;i<me.myData.length;i++) {

			if (me.dateSelected &&
				me.myData[i].event_end_date.getFullYear() >= day.getFullYear() &&
				me.myData[i].event_end_date.getMonth() >= day.getMonth() &&
				me.myData[i].event_end_date.getDate() >= day.getDate() &&
				me.myData[i].event_start_date.getFullYear() <= day.getFullYear() &&
				me.myData[i].event_start_date.getMonth() <= day.getMonth() &&
				me.myData[i].event_start_date.getDate() <= day.getDate()) {

				me.createCalEvent(me.myData[i], this.eventsContainer);
				totalEventsShown++;
			}
			else if ((!me.dateSelected) &&
				me.myData[i].event_end_date.getFullYear() >= day.getFullYear() &&
				me.myData[i].event_end_date.getMonth() >= day.getMonth() &&
				me.myData[i].event_start_date.getFullYear() <= day.getFullYear() &&
				me.myData[i].event_start_date.getMonth() <= day.getMonth()) {

				me.createCalEvent(me.myData[i], this.eventsContainer);
				totalEventsShown++;
			}
			else {
				if ($('calEvent_'+me.myData[i].event_id))
					me.removeCalEvent(me.myData[i].event_id);
			}

		}

		if (totalEventsShown == 0) {
			if (!$('no_events')) {

				var label = document.createElement('div');
				label.id = 'no_events';
				label.innerHTML = 'No events in selected calendars';
				label.style.fontStyle = 'italic';
				this.eventsContainer.appendChild(label);
			}
		}
		else {
			if ($('no_events'))
				$('no_events').remove();
		}
	}


	/*
	* showEventsLarge(day)
	*
	* Refresh the list of events in the main content area
	*/
	this.showEventsLarge = function(day) {
		var events = new Array();

		for (i=0;i<me.myData.length;i++) {

			if (me.dateSelected &&
				me.myData[i].event_end_date.getFullYear() >= day.getFullYear() &&
				me.myData[i].event_end_date.getMonth() >= day.getMonth() &&
				me.myData[i].event_end_date.getDate() >= day.getDate() &&
				me.myData[i].event_start_date.getFullYear() <= day.getFullYear() &&
				me.myData[i].event_start_date.getMonth() <= day.getMonth() &&
				me.myData[i].event_start_date.getDate() <= day.getDate()) {

				events.push(me.myData[i]);
			}
			else if ((!me.dateSelected) &&
				me.myData[i].event_end_date.getFullYear() >= day.getFullYear() &&
				me.myData[i].event_end_date.getMonth() >= day.getMonth() &&
				me.myData[i].event_start_date.getFullYear() <= day.getFullYear() &&
				me.myData[i].event_start_date.getMonth() <= day.getMonth()) {

				events.push(me.myData[i]);
			}

		}

		// Add content to container
		if (me.dateSelected) {
			me.eventLargeHeading.innerHTML = 'Events for ' + this.longDays[day.getDay()]+ ' ' + day.getDate() + '<sup>' + this.daySuffix[day.getDate()-1] + '</sup> ' + this.months[day.getMonth()] + ' ' + day.getFullYear();
		}
		else {
			me.eventLargeHeading.innerHTML = 'Events for ' + this.months[day.getMonth()] + ' ' + day.getFullYear();
		}

		// Remove existing events
		$$('.eventHolder').each(function(i) { i.remove() });

		var eventHolder = document.createElement('div');
		eventHolder.className = 'eventHolder';

		if (events.length == 0) {

			eventHolder.innerHTML = '<p><em>There are no events on this date</em></p>';
			me.eventLargeContainer.appendChild(eventHolder);

		} else {

			for (i = 0; i < events.length; i++) {

				eventHolder = document.createElement('div');
				eventHolder.className = 'eventHolder';

				if (me.dateSelected && events[i].event_start_date.getDate() == events[i].event_end_date.getDate() && events[i].event_start_date.getMonth() == events[i].event_end_date.getMonth() && events[i].event_start_date.getFullYear() == events[i].event_end_date.getFullYear()) {

					eventHolder.innerHTML = '<h4>' + events[i].event_name + '</h4>'
										  + '<h5>' + events[i].event_start_time + ' to ' + events[i].event_end_time + '</h5>'
										  + '<p>' + events[i].event_description + '</p>';
				}
				else {

					eventHolder.innerHTML = '<h4>' + events[i].event_name + '</h4>'
										  + '<h5>' + this.longDays[events[i].event_start_date.getDay()] + ' ' + events[i].event_start_date.getDate() + '<sup>' + this.daySuffix[events[i].event_start_date.getDate()-1] + '</sup> ' + this.months[events[i].event_start_date.getMonth()] + ' ' + events[i].event_start_date.getFullYear()+' to ' + this.longDays[events[i].event_end_date.getDay()] + ' ' + events[i].event_end_date.getDate() + '<sup>' + this.daySuffix[events[i].event_end_date.getDate()-1] + '</sup> ' + this.months[events[i].event_end_date.getMonth()] + ' ' + events[i].event_end_date.getFullYear() + '</h5>'
										  + '<p>' + events[i].event_description + '</p>';
				}

				me.eventLargeContainer.appendChild(eventHolder);

			}

		}
	}


	/*
	* showComingEvents()
	*
	* Refresh the list of coming events
	*/
	this.showComingEvents = function() {
		var today = new Date();
		var totalEventsShown = 0;
		for (i=0;i<me.myData.length;i++) {

			// Within the next week?
			if (me.myData[i].event_start_date.getTime() > today.getTime() &&
				me.myData[i].event_start_date.getTime() < today.getTime() + (3600*1000 *24 *7) &&
				!(me.myData[i].event_start_date.getFullYear() == today.getFullYear() &&
				  me.myData[i].event_start_date.getMonth() == today.getMonth() &&
				  me.myData[i].event_start_date.getDate() == today.getDate())) {

				me.createComingCalEvent(me.myData[i], this.container);
				totalEventsShown++;
			}
			else {
				if ($('calComingEvent_'+me.myData[i].event_id))
					me.removeComingCalEvent(me.myData[i].event_id);
			}

		}

		if (totalEventsShown == 0) {
			if (!$('no_coming_events')) {
				var label = document.createElement('div');
				label.id = 'no_coming_events';
				label.innerHTML = 'No coming events in selected calendars';
				label.style.fontStyle = 'italic';
				this.container.appendChild(label);
			}
		}
		else {
			if ($('no_coming_events'))
				this.container.removeChild($('no_coming_events'));
		}
	}


	/*
	* getCalEvents()
	*
	* Makes an AJAX request to get calendar data from the server then
	* calls the showCalEvents method to display the events
	*/
	this.getCalEvents = function() {

		new Ajax.Request(this.dateProvider + '?year=' + this.year + '&month=' + this.month, {method:'get', onSuccess:myCal.parseCalEvents, onFailure:this.errFunc});
	} // this.getCalEvents();


	this.errFunc = function(t) {
		alert('Error ' + t.status + ' -- ' + t.statusText);
	}


	/*
	* createCalEvent()
	*
	* Creates an HTML display of a calendar event.
	*/
	this.createCalEvent = function(eventData, container) {
		if(!$('calEvent_'+eventData.event_id))	 {
			thisEvent = document.createElement('div');
			thisEvent.id = 'calEvent_'+eventData.event_id
			thisEvent.className = 'calEventDetail';
			container.appendChild(thisEvent);
		}
		else {
			thisEvent = $('calEvent_'+eventData.event_id);
		}

		thisEvent.innerHTML = eventData.event_name;
	}


	/*
	* createComingCalEvent()
	*
	* Creates an HTML display of a calendar event.
	*/
	this.createComingCalEvent = function(eventData, container) {
		if(!$('calComingEvent_'+eventData.event_id))	 {
			thisEvent = document.createElement('div');
			thisEvent.id = 'calComingEvent_'+eventData.event_id
			thisEvent.className = 'calEventDetail';
			container.appendChild(thisEvent);
		}
		else {
			thisEvent = $('calComingEvent_'+eventData.event_id);
		}

		thisEvent.innerHTML = eventData.event_name;
	}


	/*
	* removeCalEvent()
	*
	* Creates an HTML display of a calendar event.
	*/
	this.removeCalEvent = function(event_id) {

		Element.remove('calEvent_'+event_id);

	}


	/*
	* removeComingCalEvent()
	*
	* Creates an HTML display of a calendar event.
	*/
	this.removeComingCalEvent = function(event_id) {
		Element.remove('calComingEvent_'+event_id);

	}


	/*
	*  calDayClick(e)
	*
	* Function to handle the event when a day is clicked
	*
	*/
	this.calDayClick = function(e) {
		elm = Event.element(e);
		elmID = elm.id != '' ? elm.id : elm.parentNode.id;
		me.selectCalDay(elmID);
	}



	/*
	* selectCalDay(elm_id, clicked)
	*
	* Hilights the current day and display that days events
	*
	*/
	this.selectCalDay = function(elm_id) {
		this.selectedDate = this.calDayDates[elm_id];
		window.location.replace(this.eventPage+'?c='+this.category+'&y='+this.selectedDate.getFullYear()+'&m='+(this.selectedDate.getMonth()+1)+'&d='+this.selectedDate.getDate());
	}




	/*
	* sortByDate(a, b)
	*
	* sort function for the myData array
	*/
	this.sortByDate = function(a, b) {
		//alert(a.event_start_date+' v '+b.event_start_date);
		var x = a.event_start_date.getTime();
		var y = b.event_start_date.getTime();
		return(x -y);
	}


}

