(function($){
	$.AboomA = {};
	
	$.AboomA.CalendarViewer = function(obj, options){
		var cv = this;
		this.$this = $(obj);
		this.options = options;
		this.label = $(options.monthLabel);
		this.backLink = $(options.back);
		this.previousLink = $(options.previous);
		this.nextLink = $(options.next);
		this.month = (new Date(options.month.getFullYear(), options.month.getMonth(), 1));
		this.eventsCache = new Object();
		this.navLevel = 0;

		this.init = function(){
			this.wrapper = $.create("div",{'class':'cvSlidingPanelsWrapper'});
			this.slider = $.create("div",{'class':'cvSlidingPanels'});
			
			
			this.days = $.create("div",{'class':'cvSlidingPanel cvMonthDays'});
			
			this.events = $.create("div",{'class':'cvSlidingPanel eventList'});
				this.eventList = $.create("ul").appendTo(this.events);
						
			this.detail = $.create("div",{'class':'cvSlidingPanel cvDetail'});
				this.detailTitle = $.create("h3", {'class':'cvDetailTitle'}).appendTo(this.detail);
				this.detailBody = $.create("div",{'class':'cvDetailBody'}).appendTo(this.detail);
			
			
			this.slider.append(this.days, this.events, this.detail).appendTo(this.wrapper);
			
			this.wrapper.appendTo(this.$this).scrollTo(0,0,{axis:'x'});
			
			this.formatEventLink = (this.options.formatEventLink != null ? this.options.formatEventLink : this.formatEventLinkDefault);
			this.formatEventDetail = (this.options.formatEventDetail != null ? this.options.formatEventDetail : this.formatEventDetailDefault);
			
			
			// Attach actions to link buttons
			this.backLink.click(this.back).hide();
			this.nextLink.click(this.next); 
			this.previousLink.click(this.previous);
			
			// Get first set of events
			this.changeMonth();
		}
		
		this.updateMonth = function(){
			this.ajax(true);
			var cvEl = this.days;
			cvEl.empty();
			
			var days = this.month.getMonthDatesSolid();
			var weeks = days.numberOfGroups(7);
			var cache = this.eventsCache;
			
			$.each(days, function(index){
				var day = $.create("div",{'class':'day normal-day empty'});
				if(this.getMonth() != cv.month.getMonth()){
					day.removeClass("normal-day").addClass("other-month-day");
				}
				var link = $.create("a",{}).append("<span>" + this.getDate() + "</span>").appendTo(day);
				if(cache[this.toId()] && this.getMonth() == cv.month.getMonth()){
					day.removeClass("empty").addClass("active");
					var date = this;
					link.attr("href","#");
					link.click(function(){
						cv.viewEvents(date);
						return false;
					})
				}
				if(weeks == 4) day.addClass("four-week-day");
				else if(weeks == 5) day.addClass("five-week-day");
				else if(weeks == 6) day.addClass("six-week-day");
				
				day.addClass(this.getDayName(true).toLowerCase());
				
				day.appendTo(cvEl);
					
			});
			cvEl.append($.create("span",{'class':'clear'}).html("&nbsp;"));
			this.updateLabel();
			this.ajax(false);
		}
		
		this.updateLabel = function(){
			var text = "";
			if(this.currentCache == null && this.currentEvent == null){
				text = this.getFormattedMonthLabel();
			} else if (this.currentCache != null){
					text = this.currentDate.getHumanDate();
			}
			this.label.html(text);
		}
		
		this.getFormattedMonthLabel = function(){
			var text = this.options.labelFormat;
			text = text.replace(/%([mMyY])/g, function(exp,found,index){
				switch(found){
					case "M":
						return cv.month.getMonthName();
					case "m":
						return cv.month.getMonthName(true);
					case "y":
						return cv.month.getFullYear().toString().substr(2,2);
					case "Y":
						return cv.month.getFullYear();
					default:
						return found;	
				}
			});
			return text;
		}
		
		this.changeMonth = function(newMonth){
			this.month = newMonth || this.month;
			if(this.eventsCache[this.month.getMonth() + "_" + this.month.getFullYear()]){
				//Events already loaded
				this.updateMonth();
			} else {
				this.ajax(true);
				var startDate = cv.month;
				var endDate = new Date(cv.month.getFullYear(), cv.month.getMonth(), cv.month.getDaysInMonth()); 
				var getOptions = {
					startDate: startDate.getDatabaseDate(true),
					endDate: endDate.getDatabaseDate(true)	
				}
				var optionsToPass = $.extend({},this.options.data,getOptions);
				$.get(this.options.path,optionsToPass,
				function(data, textstatus){
					cv.processEvents(data,textstatus,[startDate, endDate]);
				}, "json");
			}
		}
		
		this.processEvents = function(data, textStatus,monthRange){
			this.eventsCache[monthRange[0].getMonth() + "_" + monthRange[0].getFullYear()] = new Array();
			if(data.events){
			$.each(data.events, function(index){
				var evnt = new Object();
				
				evnt.eventId = this.id;
				evnt.eventType = this['type '];
				evnt.allDay = this['allDay '] == "true";
				evnt.startDate = this.startDate.getDateFromDatabase();
				evnt.endDate = this.endDate.getDateFromDatabase();
				evnt.name = this.name;
				evnt.description = this['description '];
				evnt.homeTeam = this.homeTeam;
				evnt.visitingTeam = this.visitingTeam;
				evnt.facility = this.facility;
				
				if(!cv.eventsCache[evnt.startDate.toId()])
					cv.eventsCache[evnt.startDate.toId()] = new Array();

				cv.eventsCache[evnt.startDate.toId()].push(evnt);
				cv.eventsCache[monthRange[0].getMonth() + "_" + monthRange[0].getFullYear()].push(evnt);
			});
			}
			this.updateMonth();
		}
		
		this.next = function(){
			cv.changeMonth(new Date(cv.month.getFullYear(), cv.month.getMonth() + 1, 1));
			return false;
		}
		
		this.previous = function(){
			cv.changeMonth(new Date(cv.month.getFullYear(), cv.month.getMonth() - 1, 1));
			return false;
		}
		
		this.ajax = function(action){
			if(action)
				this.$this.addClass("loading");
			else
				this.$this.removeClass("loading");
		}
		
		this.viewEvents = function(date){
			var whatToShow = this.prepareEvents(date);
			if(!whatToShow) return;
			this.currentDate = date;
			if(whatToShow == "single"){
				this.events.hide();
			} else {
				this.events.show();
			}
			this.updateLabel();
			this.detail.css('overflow','hidden');
			this.events.css('overflow','hidden');
			var showThis = (whatToShow == "single" ? this.detail : this.events);
			showThis.scrollTo(0,0);
			this.wrapper.scrollTo(showThis,this.options.duration, {axis:'x', onAfter: function(){
							showThis.css('overflow','auto');
			}});
			this.previousLink.hide();
			this.nextLink.hide();
			this.backLink.show();
		}
		
		this.prepareEvents = function(date){
			this.eventList.empty();
			var cache = this.currentCache = this.eventsCache[date.toId()];
			
			
			if(cache){
				if(cache.length == 1) {
					this.currentEvent = this.prepareEvent(cache[0]);
					return "single";
				} else {
					$.each(cache, function(index){
						var li = $.create("li").html(cv.formatEventLink(this));
					
						if(this.eventType == 1)
							li.addClass("community");
						else if(this.eventType == 2)
							li.addClass("practice");
						else if(this.eventType == 3)
							li.addClass("game");
						
						var evnt = this;
						li.click(function(e){
							$(this).addClass("selected");
							cv.showEvent(evnt);
						})
						cv.eventList.append(li);
					});
					return "multiple";
				}
			}
			return false;
			
		}
		
		this.showEvent = function(evnt){
			this.currentEvent = this.prepareEvent(evnt);
			this.events.css('overflow','hidden');
			this.detail.css('overflow','hidden');
			
			this.wrapper.scrollTo(this.detail,this.options.duration,{'axis':'x', onAfter: function(){
				cv.detail.css('overflow','auto');
			}});
			this.updateLabel();
		}
		
		this.prepareEvent = function(evnt){
			this.detailTitle.text(evnt.name);
			this.detailBody.html(this.formatEventDetail(evnt));
			return evnt;
		}
		
		
		this.back = function(){
			cv.events.css('overflow','hidden');
			cv.detail.css('overflow','hidden');
			if(cv.currentCache.length == 1 || cv.currentEvent == null){
				cv.wrapper.scrollTo(0,cv.options.duration,{axis:'x'});
				cv.currentCache = null;
				cv.currentEvent = null;
				cv.currentDate = null;
				cv.backLink.hide();
				cv.previousLink.show();
				cv.nextLink.show();

			} else {
				
				cv.wrapper.scrollTo(cv.events,cv.options.duration,{axis:'x', onAfter: function(){
					cv.events.css('overflow','auto');
				}});
				cv.currentEvent = null;
			}
			cv.updateLabel();
			return false;
		}
		
		
		this.formatEventLinkDefault = function(evnt){
			var date = (evnt.allDay ? "All Day Event" : evnt.startDate.getHumanTime() + " &mdash; " + evnt.endDate.getHumanTime());
			return "<strong>" + evnt.name + "</strong><br /><small>" + date + "</small>";
		}
		
		this.formatEventDetailDefault = function(evnt){
			var date = (evnt.allDay ? "All Day Event" : evnt.startDate.getHumanTime() + " &mdash; " + evnt.endDate.getHumanTime());
			var ret = "";
			if(evnt.description != "")
				ret += "<p>" + evnt.description + "</p>";
			ret += "<div class='cvDetailMeta'>";
			ret += "<p><strong>Time:</strong> " + date + "</p>";
			if(evnt.eventType == 2){
				ret += "<p><strong>Practice Team:</strong> " + evnt.homeTeam.name + "</p>";
			} else if (evnt.eventType == 3) {
				ret += "<p><strong>Home Team:</strong> " + evnt.homeTeam.name + "</p>";
				ret += "<p><strong>Visiting Team: </strong> " + evnt.visitingTeam.name + "</p>";
			}
			ret += "<p><strong>Facility:</strong> " + evnt.facility.name + "</p>";
			ret += "</div>";
			return ret;
		}
		
		
		
		this.$this.data("calendarViewer",this);
		this.init();
	}
	
	$.AboomA.CalendarViewer.defaults = {
		monthLabel: "#calendarViewerMonthLabel",
		previous: "#calendarViewerPrevious",
		next: "#calendarViewerNext",
		back: "#calendarViewerBack",
		path: "GetCalendarEvents.do",
		month: new Date(),
		labelFormat: "%M <small>&lsquo;%y</small>",
		formatEventLink: null,
		formatEventTitle: null,
		duration: 300,
		positionViewer: false,
		viewerParent: document.body,
		data: {}
	}

	$.fn.calendarViewer = function(options, type){
		var opts = $.extend({},$.AboomA.CalendarViewer.defaults, options);
		return this.each(function(){
			var cv = new $.AboomA.CalendarViewer(this,opts);
		});
	}
	


})(jQuery)