
var EzCalendarSheet = (function() {
	
	var self;
	var config;
	var year, month;
	var $container;
	var $details;
	
	function render() {
		$container.empty();
		
		var $table = $.c('table', false, {cellpadding: 0, cellspacing: 0, border: 0});
		var $thead = $.c('thead');
		var $tbody = $.c('tbody');
		$table.append($thead);
		$table.append($tbody);
		
		$thead.append(renderHead());
		$thead.append(renderDayNames());
		
		var $loadingTd = $.c('td', false, {colspan: 7}).html('Loading...');
		var $loadingTr = $.c('tr', 'Loading').append($loadingTd);
		$tbody.append($loadingTr);
		loadMonthData(function(data) {
			$loadingTr.remove();
			$tbody.append(renderBody($tbody, data));
		});
		
		$container.append($table);
		
		$details = $.c('div', 'Details').hide();
		$container.append($details);
	}
	
	function renderHead() {
		var $title = $.c('td', false, {colspan: 7});
		
		$title.append($.c('a', 'PrevMonth', {href: '#'}).html('&lt;&lt;')
				.click(function() {
			self.previousMonth();
			return false;
		}));
		
		$title.append('&nbsp;&nbsp;');
		
		var monthStr = month;
		if (month < 10) {
			monthStr = '0' + monthStr;
		}
		var url = config.eventList.replace('--DATE--', year+'-'+monthStr);
		$a = $.c('a', 'Month', {href: url}).html(getMonthName(month)+' '+year);
		$title.append($a);
		
		$title.append('&nbsp;&nbsp;');
		
		$title.append($.c('a', 'NextMonth', {href: '#'}).html('&gt;&gt;')
				.click(function() {
			self.nextMonth();
			return false;
		}));
		
		return $.c('tr', 'Title').append($title);
	}
	
	function renderDayNames() {
		$tr = $.c('tr', 'DayNames');
		var days = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
		for (var i = 0; i < days.length; i++) {
			var $day = $.c('td').html(days[i]);
			$tr.append($day);
		}
		return $tr;
	}
	
	function loadMonthData(callback) {
		$.ezajax('EzCalendar_Core_EventLists_CalendarSheet', 'ajaxGetEvents', {
			sources: config.sources,
			year: year,
			month: month
		}, callback, 'json');
	}
	
	function renderBody($tbody, data) {
		var today = new Date();
		var todayMonth = today.getMonth() + 1;
		var todayDay = today.getDate();
		
		var monthStr = month;
		if (month < 10) {
			monthStr = '0' + monthStr;
		}
		
		var firstDay = (new Date(year, month - 1, 1)).getDay();
		if (firstDay == 0) {
			firstDay = 7;
		}
		var lastDate = getDays(month, year);
		
		var day = 1;
		var dayStr;
		var totalRows = Math.ceil((lastDate + firstDay - 1) / 7);
		
		for (var row = 0; row < totalRows; row++) {
			var $tr = $.c('tr');
			$tbody.append($tr);
			
			for (var col = 0; col < 7; col++) {
				if (day > lastDate || (row == 0 && col < firstDay - 1)) {
					$tr.append($.c('td', 'Day Empty'));
				} else {
					dayStr = day;
					if (dayStr < 10) {
						dayStr = '0' + dayStr;
					}
					
					var sqlDate = year + '-' + monthStr + '-' + dayStr;
					var dayData = typeof data[sqlDate] != 'undefined' ? data[sqlDate] : [];
					var today = month == todayMonth && day == todayDay;
					$tr.append(renderDay(day, sqlDate, dayData, today));
					day++;
				}
			}
		}
	}
	
	function renderDay(day, sqlDate, data, today) {
		var $day = $.c('td', 'Day');
		$day.append($.c('span').html(day));
		
		if (today) {
			$day.addClass('Today');
		}
		
		var hasEvents = data.length > 0;
		$day.addClass(hasEvents ? 'HasEvents' : 'NoEvents');
		
		$day.hover(function() {
			$(this).addClass('Hover');
			if (hasEvents) {
				$details.empty();
				renderDayDetails(day, data);
				$details.show();
			}
		}, function() {
			$details.hide();
			$(this).removeClass('Hover');
		}).click(function() {
			if (hasEvents) {
				var url = config.eventList.replace('--DATE--', sqlDate);
				window.location.href = url;
			}
			return false;
		});
		
		return $day;
	}
	
	function renderDayDetails(day, data) {
		var monthName = getMonthName(month);
		var date = day + '. ' + monthName;
		
		$details.append($.c('div', 'Day').html(date));
		
		for (var i = 0; i < data.length; i++) {
			var event = data[i];
			var $event = $.c('div', 'Event');
			$event.html(event.title);
			$details.append($event);
		}
	}
	
	function leapYear(year) {
		return year % 4 == 0;
	}
	
	function getMonthName(month) {
		var monthNames = ['Januar', 'Februar', 'M&auml;rz', 'April', 'Mai', 'Juni', 'Juli',
				'August', 'September', 'Oktober', 'November', 'Dezember'];
		return monthNames[month - 1];
	}
	
	function getDays(month, year) {
		var days = [31, leapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
		return days[month - 1]
	}
	
	return {
		
		init: function(configuration) {
			$(document).ready(function() {
				
				self = EzCalendarSheet;
				config = configuration;
				$container = $('#EzCalendarSheet');
				
				var year, month;
				if (window.location.href.indexOf('?date=') > -1) {
					var start = window.location.href.indexOf('?date=') + 6
					var length = 7;
					var date = window.location.href.substring(start, start + length);
					year = parseInt(date.substring(0, 4), 10);
					month = parseInt(date.substring(5, 7), 10);
				} else {
					var today = new Date();
					year = today.getYear();
					if (year < 1000) {
						year += 1900;
					}
					month = today.getMonth() + 1;
				}
				
				self.setMonth(month);
				self.setYear(year);
				self.render();
			});
		},
		
		setMonth: function(monthVal) {
			month = parseInt(monthVal, 10);
		},
		
		getMonth: function() {
			return month;
		},
		
		setYear: function(yearVal) {
			year = parseInt(yearVal, 10);
		},
		
		getYear: function() {
			return year;
		},
		
		previousMonth: function() {
			month--;
			if (month < 1) {
				month = 12;
				year--;
			}
			self.render();
		},
		
		nextMonth: function() {
			month++;
			if (month > 12) {
				month = 1;
				year++;
			}
			self.render();
		},
		
		render: function() {
			render();
		}
		
	}
	
})();
