var Calendar = new Class({
	
	Implements: [Options, Events],
	options: {
		calContainer: 'calBody', // id of the element that the calendar will be "injected" into
		newDate: 0, // used to set the initial selected date to one other than the current day
		view: 'month', // options are: month, week, day - sets the default view
		calDate: new Date(), // tracks the selected calendar date - can be varied by newDate:
		todayDate: new Date(), // sets the permanent day for cell coloring
		navPrevDate: new Date(), // sets date for previous calendar
		navNextDate: new Date(), // sets date for next calendar
		days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
		months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
		daysInMonth: 30, // can be set with setDaysInMonth(month,year)
		startingOffset: 0, // determine the offset of the first of the month and Sunday - used for the "month" view
		viewStartDate: new Date(), // used to get events
		viewEndDate: new Date() // used to get events
	},
	initialize: function(options){
		this.setOptions(options);
		this.options.newDate != 0 ? this.options.calDate = new Date(this.options.newDate) : this.options.calDate = new Date();
		this.options.newDate != 0 ? this.options.navPrevDate = new Date(this.options.newDate) : this.options.navPrevDate = new Date();
		this.options.newDate != 0 ? this.options.navNextDate = new Date(this.options.newDate) : this.options.navNextDate = new Date();
		this.setCalParams();
		this.extendDate();
		this.showMonth();
	},
	setDaysInMonth: function(month, year){ // month: must be an integer (0 - 11) year: used to dertermine if leap year exists
		var daysInMonths = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
		if(new Date(year,1,29).getDate() == 29) // determine if leap year
			daysInMonths[1] = 29;
		this.options.daysInMonth = daysInMonths[month];
	},
	setStartingOffset: function(month,year){ // month: must be an integer (0 - 11)
		this.options.startingOffset = new Date(year,month,1).getDay();
	},
	setDate: function(day){
		this.options.calDate.setDate(day);
	},
	setCalParams: function(){
		this.setDaysInMonth(this.options.calDate.getMonth(), this.options.calDate.getFullYear());
		this.setStartingOffset(this.options.calDate.getMonth(), this.options.calDate.getFullYear());
	},
	navPrevMonth: function(){ 
		var pDate = this.options.navPrevDate.getMonth();
		this.options.navPrevDate.setMonth(pDate-1);
		var navPrevLink = [this.options.navPrevDate.getMonth()+1]+'-'+[this.options.navPrevDate.getFullYear()];
		return navPrevLink;
	},
	navNextMonth: function(){ 
		var nDate = this.options.navNextDate.getMonth();
		this.options.navNextDate.setMonth(nDate+1);
		var navNextLink = [this.options.navNextDate.getMonth()+1]+'-'+[this.options.navNextDate.getFullYear()];
		return navNextLink;
	},
	showControlsRow: function(calTitle){
		var trC = new Element('tr');
		var thL = new Element('th', {'colspan': '2','width':'30%','class':'calHead','id':'navlinks'}).inject(trC);
		var prevCal = new Element('a',{'href':'?d=' + this.navPrevMonth(),'class':'prevCal'}).set('html','&lt; Previous').inject(thL);
		var thC = new Element('th',{'colspan':'3','class':'calHead'}).set('html',calTitle).inject(trC);
		var thR = new Element('th',{'colspan':'2','class':'calHead','id':'navlinks'}).inject(trC);
		var nextCal = new Element('a',{'href':'?d=' + this.navNextMonth(),'class':'nextCal'}).set('html','Next &gt;').inject(thR);
		return trC;
	},
	showMonth: function(){
		$(this.options.calContainer).set('html','');
		//this.options.view = 'month';
		var table = new Element('table',{'class':'mooECal','id':'monthCal'});
		var thead = new Element('thead').inject(table);
		var tbody = new Element('tbody').inject(table);

		this.showControlsRow(this.options.months[this.options.calDate.getMonth()]+' '+this.options.calDate.getFullYear()).inject(thead);

		var tr = new Element('tr',{'class':'dowRow'}).inject(thead);
		for (var i = 0; i < 7; i++){
			var th = new Element('th').set('text', this.options.days[i]).inject(tr);
		}
		var calDone = false;
		for (var i = 0; i < 6; i++){
			
			if(calDone){
				if(i == 5) // 5 week rows
					table.set({'styles':{'height':'auto'}})
				else if(i==4) // 4 week rows
					table.set({'styles':{'height':'auto'}})
				break;
			}
			var tr = new Element('tr',{'class':'monthWeek'}).inject(tbody); // create weeks
			for (var j = 0; j < 7; j++) {
				var day = ((j+1) + (i*7)) - this.options.startingOffset;
				var td = new Element('td',{'class':'monthDay','id':'day'+day}).inject(tr); // create days
				if (day > 0 && day <= this.options.daysInMonth){
					td.set({
						events: {
							'mouseover': function(){this.addClass('hover')},
							'mouseout': function(){this.removeClass('hover')}
						}
					});
					new Element('span',{'text':day}).store('date',day).inject(td); //writes day numbers
					td.store('date',day);
					new Element('div',{'height':'100%','styles':{'height':'auto','overflow':'hidden'}}).store('date',day).inject(td);
					//set background color for current day
					if(day == this.options.todayDate.getDate() && this.options.calDate.getMonth() == this.options.todayDate.getMonth() && this.options.calDate.getYear() == this.options.todayDate.getYear()) 
						td.addClass('selected');
					if(day == this.options.daysInMonth) // comment out for a fixed height calendar
						calDone = true;
				}
				else{
					td.set('html', '&nbsp;'); // IE won't show td borders without something in the cell
				}
				td.fade('hide');
				td.fade('in');
			}
		}
		this.options.viewStartDate.setTime(this.options.calDate.valueOf());
		this.options.viewStartDate.setDate(1);
		this.options.viewEndDate.setTime(this.options.calDate.valueOf());
		this.options.viewEndDate.setDate(this.options.daysInMonth);
		this.options.viewStartDate.startOfDay();
		this.options.viewEndDate.endOfDay();
		table.inject($(this.options.calContainer));
		this.loadCalEvents();
	}, // end of showMonth
	loadCalEvents: function(){
		$$('div.tip').each(function(divs){divs.getParent().destroy();}); // Tips cleanup - tip divs kept building up after switching calendar views
		for(var i = 0; i < cEvents.length; i++){
			cEvents[i].eventDate = new Date(cEvents[i].eventDate);
			if(cEvents[i].eventDate >= this.options.viewStartDate && cEvents[i].eventDate <= this.options.viewEndDate){
				if(cEvents[i].eventSponsor == 't'){
					var eventDiv = new Element('div',{
						'class':'title-sponsor','html':cEvents[i].eventTitle
					}).store('date',cEvents[i].eventDate.getDate()).inject($('day'+cEvents[i].eventDate.getDate()).getChildren('div')[0]);}
					else {
					var eventDiv = new Element('div',{
						'html':cEvents[i].eventTitle
					}).store('date',cEvents[i].eventDate.getDate()).inject($('day'+cEvents[i].eventDate.getDate()).getChildren('div')[0]);}

				if (this.options.view != 'month') // the month view only shows a portion of the event description
					eventDiv.addClass('fullEvent');
				else {
					new Tips(eventDiv, {onShow: function(tip){tip.setStyle('opacity', '1');}});
					eventDiv.store('tip:text',cEvents[i].eventName);
				}
			}
		}
	},
extendDate: function(){ 
		function startOfDay(){
			this.setHours(0);
			this.setMinutes(0);
			this.setSeconds(0);
			this.setMilliseconds(0);
		};
		function endOfDay(){
			this.setHours(23);
			this.setMinutes(59);
			this.setSeconds(59);
			this.setMilliseconds(999);
		};
		Date.prototype.startOfDay = startOfDay;
		Date.prototype.endOfDay = endOfDay;
	}
});