var Calendar = new Class.create({
	initialize: function(start, element) {
		this.container = $(element);
		this.startDate = (start) ? new Date(start) : this.getStartDate();
		this.selectedDate = new Date(this.startDate);
		this.startDate.setDate(1);
		this.currentEvents = [];
		this.currentDate;
		
		this.tableString = '<table class="'+Calendar.classes.table+'">';
		this.createHeaderString();
		this.createCalendarString();
		this.endCalendarString();
		this.addCalendar();
		this.selectDate(this.selectedDate);
	},
	getStartDate: function() {
		var date = new Date()
		date.setHours(0); date.setMinutes(0); date.setSeconds(0); date.setMilliseconds(0);
		date = date.valueOf();
		pickedDate = new Date().setFullYear(2020);
		pickedDate = pickedDate.valueOf();
		var datePicked = false;
		Calendar.events.each(function(ev) {
			var evDate = new Date(ev.date);
			evDate = evDate.valueOf();
			if(evDate > date && evDate <= pickedDate) {
				pickedDate = evDate;
			}
		});
		return new Date(pickedDate);
	},
	createHeaderString: function() {
		this.tableString += '<caption><a class="'+Calendar.ids.prevMonth+'" id="'+Calendar.ids.prevMonth+'" href="#prev">Previous Month</a><a class="'+Calendar.ids.nextMonth+'" id="'+Calendar.ids.nextMonth+'" href="#prev">Next Month</a>'+Calendar.format.months[this.startDate.getMonth()]+' '+this.startDate.getFullYear()+'</caption>';
		
		this.tableString += '<tr>';
		Calendar.format.days.each(function(str) {
			this.tableString += '<th class="'+Calendar.classes.day_header+'">'+str+'</th>';
		}, this);
		this.tableString += '</tr>';
	},
	createCalendarString: function() {
		this.tableString += '<tr>';
		var firstDay = this.findMonthStart(this.startDate);
		for(var i = 0; i < firstDay; i++) {
			this.tableString += '<td class="'+Calendar.classes.out_of_month+'"></td>';
		}
		
		var date = new Date(this.startDate);
		while(date.valueOf() == this.startDate.valueOf() || date.getDate() != 1) {
			if(date.getDay() == 0) {
				this.tableString += '</tr><tr>';
			}
			
			this.tableString += this.getDateHTML(date);
			date.setDate(date.getDate() + 1);
		}
		
		return this.tableString;
	},
	getDateHTML: function(date) {
		var dayClass = this.getDayClass(date);
		
		//var dayHTML = new Element('td', { class: dayClass, rel: date.toString() }).update(date.getDate());
		var dayHTML = '<td class="'+dayClass+'" rel="'+date.toString()+'">'+date.getDate()+'</td>';

		return dayHTML;
	},
	getDayClass: function(date) {
		var dayClass = '';

		Calendar.events.each(function(event) { 
			if(event.date.valueOf() == date.valueOf()) { 
				dayClass += ' '+Calendar.classes.has_event;
			}
		});
		
		var today = new Date();
		today.setMinutes(0); today.setHours(0); today.setSeconds(0); today.setMilliseconds(0);
		
		if(date.valueOf() == today.valueOf()) { dayClass += ' '+Calendar.classes.today; }
		
		if(date.getMonth() != this.startDate.getMonth()) {
			dayClass += ' '+Calendar.classes.out_of_month;
		}
		
		return dayClass;
	},
	findMonthStart: function(date) {
		date.setDate(1);
		return date.getDay();
	},
	endCalendarString: function() {
		this.tableString += '</tr></table>';
		
		return this.tableString;
	},
	addCalendar: function() {
		this.container.update();
		this.container.insert(this.tableString);
		
		this.attachEvents();
	},
	attachEvents: function() {
		$$('.'+Calendar.classes.has_event).invoke('observe', 'click', this.getNewEvents.bindAsEventListener(this));
		$(Calendar.ids.prevMonth).observe('click', this.prevMonth.bindAsEventListener(this));
		$(Calendar.ids.nextMonth).observe('click', this.nextMonth.bindAsEventListener(this));
	},
	nextMonth: function(event) {
		Event.stop(event);
		this.startDate.setMonth(this.startDate.getMonth()+1);
		this.changeMonth(this.startDate);
	},
	prevMonth: function(event) {
		Event.stop(event);
		this.startDate.setMonth(this.startDate.getMonth()-1);
		this.changeMonth(this.startDate);
	},
	changeMonth: function(date) {
		this.startDate = date;
		this.tableString = '<table class="'+Calendar.classes.table+'">';
		this.createHeaderString();
		this.createCalendarString();
		this.endCalendarString();
		this.addCalendar();
	},
	clearCurrentEvents: function() {
		this.currentEvents.length = 0;
		$(Calendar.ids.event_list).down('ul').update();
	},
	updateCurrentEvents: function(key) {
		var ev = this.currentEvents[key];
		$(Calendar.ids.event_list).down('ul').insert(ev.listEl);
		if(!$('event-short-list')) {
		    var links = $(ev.listEl).select('a');
    		links[links.length-1].observe('click', this.selectEvent.bindAsEventListener(this));
		}
	},
	selectEvent: function(event) {
		Event.stop(event);
		
		var key = event.target.readAttribute('rel').replace('key-', '');
		
		$(Calendar.ids.event_feature).update(this.currentEvents[key]['body']);
	},
	selectDate: function(date) {
		this.getNewEvents(null, date);
	},
	getNewEvents: function(event, date) {
		if(event) {
			if(event.target.hasClassName(Calendar.classes.selected)) { return; }
			$$('.'+Calendar.classes.selected).invoke('removeClassName', Calendar.classes.selected);
			event.target.addClassName(Calendar.classes.selected);
			var date = new Date(event.target.readAttribute('rel'));
		} else {
			$$('.'+Calendar.classes.table)[0].select('td').each(function(td) {
				var d = new Date(td.readAttribute('rel'));
				if(d.valueOf() == date.valueOf()) {
					td.addClassName(Calendar.classes.selected);
				}
			});
			date = new Date(date);
		}
		this.clearCurrentEvents();

		Calendar.events.each(function(event) { 
			if(event.date.valueOf() == date.valueOf()) { 
		        new Ajax.Request(Calendar.eventLocations + event.url + Calendar.eventSummarySuffix, {
		            method: 'get',
					onFailure: function() {
						alert('We\'re sorry, but there was an error retrieving events. Please refresh this page and try again.');
					},
		            onSuccess: function(o) {
						var a = String.toHTML(o.responseText);
						var link = $(a).select('a');
	                    link = link[link.length-1]
						var ev = {
							title: $(a).down('h2').innerHTML,
							url: link.readAttribute('href'),
							body: o.responseText
						};
						Object.extend(ev, {
							listEl: new Element('li').update(new Element('a', { href: ev.url, rel: 'key-'+this.currentEvents.length }).update(ev.title+' &raquo;'))
						});
						this.currentEvents.push(ev);
						this.updateCurrentEvents(this.currentEvents.length-1);
		            }.bind(this)
	        	});
			}
		}, this);
	}
});
Object.extend(Calendar, {
	events: [],
	format: {
		months: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
		days: [ 'S', 'M', 'T', 'W', 'T', 'F', 'S' ]
	},
	classes: {
		table: 'cal-calendar',
		day_header: 'cal-cel',
		today: 'today',
		out_of_month: 'cal-disabled',
		has_event: 'cal-event',
		selected: 'cal-selected'
	},
	ids: {
		prevMonth: 'cal-navleft',
		nextMonth: 'cal-navright',
		event_list: 'event-list',
		event_feature: 'event-feature'
	},
	eventLocations: '/svc/event/',
	eventSummarySuffix: '/brief/'
});

Object.extend(String, {
	toHTML: function(str) {
		var d = document.createElement('div');
		d.innerHTML = str;
		return d;
	}
})