Papercut.Calendar = Class.create({
	version: 0.1,
	container: null,
	currentDate: new Date(),
	preload: 1,
	
	events: new Object(),
	eventsByItemId: new Object(),
	eventsFullDay: new Object(),
	eventsTimed: new Object(),
	eventsSorted: new Object(),
	
	loadedMonths: new Object(),
	visibleCalendars: new Object(),
	
	displays: null,
	pendingRequests: 0,
	
	initialize: function(id, options) {
		this.setOptions(options);
		
		this.container = $(id);
		
		this.initDisplays();
		this.loadCurrentMonth();
		
		//console.log(this);
	},
	
	loadCurrentMonth: function() {
		//console.log('load current month');
		this.loadEvents(this.currentDate.getMonth(), this.currentDate.getDate(), this.currentDate.getFullYear(), true);
		this.preloadEvents();
	},
	
	draw: function(called) {
		//console.log('draw ' + called);
		for (var i = 0; i < this.displays.length; i++) {
			this.displays[i].currentDate.setTime(this.currentDate.getTime());
			this.displays[i].draw();
		}
	},
	
	initDisplays: function() {
		//console.log('init displays');
		if (this.displays != null) {
			for (var i = 0; i < this.displays.length; i++) {
				this.displays[i].calendar = this;
				this.displays[i].currentDate.setTime(this.currentDate.getTime());
			}
		}
		else {
			
		}
	},
	
	loadEvents: function(month, date, year, redraw) {
		if (redraw == null) redraw = false;
		//console.log('loadEvents('+month + ', ' + date + ', ' + year + ', ' + redraw + ')');
		var monthDate = new Date();
		monthDate.setFullYear(year, month, date);
		var monthIndex = monthDate.getYearMonth();
		//console.log('checking ' + monthIndex);
		if (this.loadedMonths[monthIndex] == null) {
			//console.log('need to load');
			this.loadedMonths[monthIndex] = true;
			this.pendingRequests++;
			var url = '/calendar/calendar.php';
			var pars = Object.toQueryString({
				action:'loadEvents',
				month:month,
				date:date,
				year:year
			});
			new Ajax.Request(url, {
				postBody: pars,
				onComplete: function(transport) {
					var response = transport.responseJSON;
					var events = response.events;
					var di = 0;
					var d = null;
					for (var i = 0; i < events.length; i++) {
						d = new Date();
						d.setTime(events[i].eiStartTime*1000);
						di = d.makeDateIndex();
						if (this.events[di] == null) {
							this.events[di] = new Array();
						}
						
						this.events[di].push(events[i]);
						this.eventsSorted[di] = false;
						this.eventsByItemId[events[i].eventItemId] = events[i];
						if (events[i].allDay == '1' || (events[i].stopTime - events[i].startTime > 86400)) {
							if (this.eventsFullDay[di] == null) {
								this.eventsFullDay[di] = new Array();
							}
							this.eventsFullDay[di].push(events[i]);
						}
						else {
							// these events have a specific time and are only one day
							if (this.eventsTimed[di] == null) {
								this.eventsTimed[di] = new Array();
							}
							this.eventsTimed[di].push(events[i]);
						}
					}
					if (redraw) {
						this.draw('if redraw 1');
					}
				}.bind(this)
			});
		}
		else {
			//console.log('already loaded');
			if (redraw) {
				this.draw('if redraw 2');
			}
		}
	},
	
	sort: function(a, b) {
		return (a.eiStartTime - b.eiStartTime);
	},
	
	preloadEvents: function() {
		//console.log('preload events');
		if (this.preload) {
			for (var i = this.currentDate.getMonth() - this.preload; i <= this.currentDate.getMonth() + this.preload; i++) {
				this.loadEvents(i, this.currentDate.getDate(), this.currentDate.getFullYear());
			}
		}
	},
	
	setFullYear: function(year, month, date) {
		if (month == null) month = this.currentDate.getMonth();
		if (date == null) date = this.currentDate.getDate();
		//console.log('set full year ' + year + ' ' + month + ' ' + date);
		this.currentDate.setFullYear(year, month, date);
		this.loadCurrentMonth();
	},
	
	setMonth: function(month) {
		//console.log('set month ' + month);
		this.currentDate.setMonth(month);
		this.loadCurrentMonth();
	},
	
	makeDateIndex: function(d) {
		return d.getFullYear() + '/' + (d.getMonth()).toString() + '/' + d.getDate();
	},
	
	setOptions: function(options) {
		for (var i in options) {
			this[i] = options[i];
		}
	}
});

Papercut.CalendarDisplay = {};
Papercut.CalendarDisplay.DayMonthYear = Class.create({
	version: 0.1,
	container: null,
	currentDate: new Date(),
	calendar: null,
	
	initialize: function(id, options) {
		this.setOptions(options);
		this.container = $(id);
		
	},
	
	draw: function() {
		this.container.innerHTML = this.currentDate.getDayName() + ', ' + this.currentDate.getMonthName() + ' ' + this.currentDate.getDate() + ', ' + this.currentDate.getFullYear();
	},
	
	setOptions: function(options) {
		for (var i in options) {
			this[i] = options[i];
		}
	}
});

Papercut.CalendarDisplay.YearNav = Class.create({
	version: 0.1,
	container: null,
	currentDate: new Date(),
	calendar: null,
	
	initialize: function(id, options) {
		this.setOptions(options);
		this.container = $(id);
		this.container.hide();
		this.container.innerHTML = '<span class="yearNavLeftArrow">&lt;</span><span class="yearNavRightArrow">&gt;</span><span class="yearNavTitle"></span><div class="clear"></div>';
		
		this.previousController = $(this.container.childNodes[0]);
		this.yearDisplay = $(this.container.childNodes[2]);
		this.nextController = $(this.container.childNodes[1]);
		
		this.previousController.observe('click', function() {
			//console.log('previous year');
			this.calendar.setFullYear(this.currentDate.getFullYear() - 1);
		}.bindAsEventListener(this));
		
		this.nextController.observe('click', function() {
			//console.log('next year');
			this.calendar.setFullYear(this.currentDate.getFullYear() + 1);
		}.bindAsEventListener(this));
		
	},
	
	draw: function() {
		this.yearDisplay.innerHTML = this.currentDate.getFullYear();
		this.container.show();
	},
	
	setOptions: function(options) {
		for (var i in options) {
			this[i] = options[i];
		}
	}
});

Papercut.CalendarDisplay.AllMonthNav = Class.create({
	version: 0.1,
	container: null,
	currentDate: new Date(),
	calendar: null,
	activeItem: null,
	
	initialize: function(id, options) {
		this.setOptions(options);
		this.container = $(id);
		
		this.container.hide();
		this.container.innerHTML = '<span>Jan</span><span>Feb</span><span>Mar</span><span>Apr</span><span>May</span><span>Jun</span><span>Jul</span><span>Aug</span><span>Sep</span><span>Oct</span><span>Nov</span><span>Dec</span><div class="clear"></div>';
		
		for (var i = 0; i < 12; i++) {
			el = $(this.container.childNodes[i]);
			
			el.observe('click', function(e, el, i) {
				this.calendar.setMonth(i);
			}.bindAsEventListener(this, el, i));
			
			el.observe('mouseover', function(e, el) {
				el.addClassName('hover');
			}.bindAsEventListener(this, el));
			
			el.observe('mouseout', function(e, el) {
				el.removeClassName('hover');
			}.bindAsEventListener(this, el));
		}
		
		this.container.childNodes[6].addClassName('break');
	},
	
	draw: function() {
		if (this.activeItem != null) {
			this.activeItem.removeClassName('active');
		}
		this.container.show();
		this.activeItem = $(this.container.childNodes[this.currentDate.getMonth()]);
		this.activeItem.addClassName('active');
	},
	
	setOptions: function(options) {
		for (var i in options) {
			this[i] = options[i];
		}
	}
});

Papercut.CalendarDisplay.SmallMonthDisplay = Class.create({
	version: 0.1,
	container: null,
	currentDate: new Date(),
	calendar: null,
	cachedViews: new Object(),
	activeItem: null,
	visibleContainer: null,
	
	initialize: function(id, options) {
		this.setOptions(options);
		this.container = $(id);
		this.createContainer();
	},
	
	createContainer: function() {
		//console.log('create small cal');
		this.container.hide();
		this.container.addClassName('smallCalendar');
		var str = '';
		str += '<table cellpadding="0" cellspacing="0" width="100%" class="calendarSmall">';
		str += '<tr><td>';
		str += '<table width="100%"><tr>';
		str += '<td width="80%" class="monthName" align="center"></td>';
		str += '</tr></table></td></tr>';
		str += '<tr><td><table width="100%" class="calendarDayNames">';
		str += '<tr class="smallCalendarDayTitles"><td width="20">Sun</td><td width="20">Mon</td><td width="20">Tue</td><td width="20">Wed</td><td width="20">Thu</td><td width="20">Fri</td><td width="20">Sat</td></tr></table></td></tr>';
		str += '<tr><td><div class="calendarDates">';
		str +='</div></td></tr></table>';
		this.container.innerHTML = str;
		
		this.monthName = this.container.select('.monthName')[0];
		this.calendarDates = this.container.select('.calendarDates')[0];
	},
	
	draw: function() {
		//console.log('draw small month');
		this.monthName.innerHTML = this.currentDate.getMonthName();
		
		if (this.visibleContainer != null) {
			this.visibleContainer.hide();
		}
		
		var cacheIndex = this.currentDate.getYearMonth();
		//var drawContainerId = 'cacheSmallMonthDisplay'+cacheIndex; // doesn't work in webkit
		var drawContainerId = 'cacheSmallMonthDisplay'+this.currentDate.getMonth()+'-'+this.currentDate.getFullYear();
		
		if (this.cachedViews[cacheIndex] == null) {
			var str = '<table width="100%">';
			var firstSunday = this.currentDate.firstSunday();
			var lastSaturday = this.currentDate.lastSaturday();
			var cellContent = '';
			var di = '';
			for (var i = firstSunday; i.getTime() <= lastSaturday.getTime(); i = i.nextDay()) {
				if (i.getDay() == 0) {
					str += '<tr>';
				}
				if (i.getMonth() == this.currentDate.getMonth()) {
					cellContent = i.getDate();
				}
				else {
					cellContent = '';
				}
				di = i.makeDateIndex();
				str += '<td id="smallMonthDisplay-'+di+'" class="smallDate">' + cellContent + '</td>';
			}
			str += '</table>';
			
			this.cachedViews[cacheIndex] = true;
			var drawContainer = document.createElement('div');
			drawContainer.id = drawContainerId;
			drawContainer.innerHTML = str;
			this.calendarDates.appendChild(drawContainer);
			this.visibleContainer = $(drawContainerId);
			
			var cells = this.visibleContainer.select('.smallDate');
			for (var i = 0; i < cells.length; i++) {
				
				tempDi = cells[i].id.split('-')[1];
				if (this.calendar.events[tempDi] != null) {
					cells[i].addClassName('hasEvents');
				}
				
				cells[i].observe('click', function(e, el) {
					parts = el.id.split('-')[1].split('/');
					this.calendar.setFullYear(parts[0], parts[1], parts[2]);
				}.bindAsEventListener(this, cells[i]));
				
				cells[i].observe('mouseover', function(e, el) {
					el.addClassName('hover');
				}.bindAsEventListener(this, cells[i]));
				
				cells[i].observe('mouseout', function(e, el) {
					el.removeClassName('hover');
				}.bindAsEventListener(this, cells[i]));
			}
		}
		else {
			this.visibleContainer = $(drawContainerId);
		}
		
		this.visibleContainer.select('.active').each(function(e) {e.removeClassName('active')});
		this.activeItem = $('smallMonthDisplay-' + this.currentDate.makeDateIndex());
		this.activeItem.addClassName('active'); // error here
		
		this.visibleContainer.show();
		this.container.show();
		
	},
	
	setOptions: function(options) {
		for (var i in options) {
			this[i] = options[i];
		}
	}
});

Papercut.CalendarDisplay.WeekAtGlance = Class.create({
	version: 0.1,
	container: null,
	currentDate: new Date(),
	calendar: null,
	cachedViews: new Object(),
	visibleContainer: null,
	
	initialize: function(id, options) {
		this.setOptions(options);
		this.container = $(id);
		
		this.container.hide();
		this.container.innerHTML = '<div class="weekAtGlanceContainer"><div class="weekAtGlanceHeader">Week at a Glance</div><div></div></div>';
		
		this.content = $(this.container.childNodes[0].childNodes[1]);
	},
	
	draw: function() {
		//console.log('draw week at glance');
		if (this.visibleContainer != null) {
			this.visibleContainer.hide();
		}
		
		var cacheIndex = this.currentDate.makeDateIndex();
		// var drawContainerId = 'cacheWeekAtGlance'+cacheIndex; // doesn't work in webkit
		var drawContainerId = 'cacheWeekAtGlance'+this.currentDate.getDate()+'-'+this.currentDate.getMonth()+'-'+this.currentDate.getFullYear();
		
		if (this.calendar.eventsSorted[cacheIndex] != null && this.calendar.eventsSorted[cacheIndex] == false) {
			//console.log('need to sort');
			this.calendar.events[cacheIndex].sort(this.calendar.sort);
			this.calendar.eventsSorted[cacheIndex] = true;
		}
		if (this.cachedViews[cacheIndex] == null) {
			var str = '';
			var oneWeek = new Date();
			oneWeek.setTime(this.currentDate.getTime());
			oneWeek.setDate(oneWeek.getDate()+7);
			var di = '';
			var num = 0;
			for (var i = this.currentDate; i.getTime() < oneWeek.getTime(); i = i.nextDay()) {
				di = i.makeDateIndex();
				num = 0;
				if (this.calendar.events[di] != null) {
					str += '<div class="weekAtGlanceDay" id="weekAtGlanceDay-'+di+'"><div class="weekAtGlanceDayName">' + i.getDayName() + ', ' + i.getDate() + '</div>';
					num = this.calendar.events[di].length;
					for (var j = 0; j < num; j++) {
						str += '<div class="weekAtGlanceTitle">'+this.calendar.events[di][j].title+'</div>';
						eventTime = new Date();
						eventTime.setTime(this.calendar.events[di][j].eiStartTime*1000);
						str += '<div class="weekAtGlanceTime">'+eventTime.getHours12() + ':' + eventTime.getMinutes2() +  eventTime.getAmpm() + '</div>';
					}
					str += '</div>';
				}
			}
			
			this.cachedViews[cacheIndex] = true;
			var drawContainer = document.createElement('div');
			drawContainer.id = drawContainerId;
			drawContainer.innerHTML = str;
			this.content.appendChild(drawContainer);
			drawContainer = $(drawContainer);
			var eachDay = drawContainer.select('.weekAtGlanceDay');
			
			for (var i = 0; i < eachDay.length; i++) {
				eachDay[i].observe('click', function(e, el) {
					parts = el.id.split('-')[1].split('/');
					this.calendar.setFullYear(parts[0], parts[1], parts[2]);
				}.bindAsEventListener(this, eachDay[i]));
				
				eachDay[i].observe('mouseover', function(e, el) {
					el.addClassName('hover');
				}.bindAsEventListener(this, eachDay[i]));
				
				eachDay[i].observe('mouseout', function(e, el) {
					el.removeClassName('hover');
				}.bindAsEventListener(this, eachDay[i]));
				
			}
			
		}
		else {
			
		}
		this.visibleContainer = $(drawContainerId);
		this.visibleContainer.show();
		this.container.show();
	},
	
	setOptions: function(options) {
		for (var i in options) {
			this[i] = options[i];
		}
	}
});


Papercut.CalendarDisplay.DayDetails = Class.create({
	version: 0.1,
	container: null,
	currentDate: new Date(),
	calendar: null,
	cachedViews: new Object(),
	visibleContainer: null,
	
	initialize: function(id, options) {
		this.setOptions(options);
		this.container = $(id);
		
		this.container.hide();
		this.container.innerHTML = '<div class="dayDetailsContainer"></div>';
		this.content = $(this.container.childNodes[0]);
	},
	
	draw: function() {
		//console.log('draw day details');
		
		if (this.visibleContainer != null) {
			this.visibleContainer.hide();
		}
		
		var cacheIndex = this.currentDate.makeDateIndex();
		//var drawContainerId = 'cacheDayDetails'+cacheIndex; // doesn't work in webkit
		var drawContainerId = 'cacheDayDetails'+this.currentDate.getDate()+'-'+this.currentDate.getMonth()+'-'+this.currentDate.getFullYear();
		
		if (this.calendar.eventsSorted[cacheIndex] != null && this.calendar.eventsSorted[cacheIndex] == false) {
			//console.log('need to sort');
			this.calendar.events[cacheIndex].sort(this.calendar.sort);
			this.calendar.eventsSorted[cacheIndex] = true;
		}
		
		if (this.cachedViews[cacheIndex] == null) {
			var str = '';
			var num = 0;
			if (this.calendar.events[cacheIndex]!= null) {
				num = this.calendar.events[cacheIndex].length;
				for (var i = 0; i < num; i++) {
					str += '<div class="dayDetailsTitle">'+this.calendar.events[cacheIndex][i].title+'</div>';
					eventTime = new Date();
					eventTime.setTime(this.calendar.events[cacheIndex][i].eiStartTime*1000);
					str += '<div class="dayDetailsTime">'+eventTime.getHours12() + ':' + eventTime.getMinutes2() +  eventTime.getAmpm() + '</div>';
					str += '<div class="dayDetailsDescription">'+this.calendar.events[cacheIndex][i].description+'</div>';
				}
			}
			else {
				str += '<div>No events for this day...</div>';
			}
			this.cachedViews[cacheIndex] = true;
			var drawContainer = document.createElement('div');
			drawContainer.id = drawContainerId;
			drawContainer.innerHTML = str;
			this.container.appendChild(drawContainer);
		}
		
		this.visibleContainer = $(drawContainerId);
		this.visibleContainer.show();
		this.container.show();
	},
	
	setOptions: function(options) {
		for (var i in options) {
			this[i] = options[i];
		}
	}
});

