(function($){

$(calendar);

// This function runs once on page load;
function calendar() {
	var calendar = $('div.calendar'), outerWrapHTML = '<div id="calendarOuterWrap"><div id="calendarWrap"><div/></div></div>';
	if (calendar.length) calendar.wrap(outerWrapHTML);
	else $('#dateBar').after(outerWrapHTML);

	// Prettify the datepicker selectbox
	$('#selectMonth:not(.processed)', this).addClass('processed').selectbox().change(function() {
		$(this).parents('form:first').submit();
	}).next().remove();

	$('#calendarBlockHome').each(function() {
		var self = $(this).addClass('calendarOpen'), datebar = $('#dateBar'), outerWrap = $('#calendarOuterWrap'), wrap = $('#calendarWrap');
		outerWrap.css({position: 'relative', overflow: 'hidden', zIndex: 1});
		
		$('<div class="toggleIcon"/>').prependTo(datebar).hoverClass('toggleHover').click(function() {
			self.trigger('toggleOpen');
		}).css('opacity', 0.7).hover(function(){ $(this).stop().fadeTo(300, 1); }, function(){ $(this).stop().fadeTo(300, 0.7); });
		
		self.bind('toggleOpen', function(e, callback) {
			self.trigger(self.is('.calendarOpen') ? 'closeCalendar' : 'openCalendar', callback);
		}).bind('closeCalendar', function(e, callback) {
			wrap.stop().animate({marginTop: -wrap.outerHeight()}, 'slow', 'easeOutCubic', callback);
			self.addClass('calendarClosed').removeClass('calendarOpen');
			// When we close the calendar, add a one time click bind to the daylist to open the calendar again.
			$('div.dayList a.activeItem').one('click', function() {
				self.trigger('openCalendar');
			});
		}).bind('openCalendar', function(e, callback) {
			wrap.stop().animate({marginTop: 0}, 'slow', 'easeOutCubic', callback);
			self.addClass('calendarOpen').removeClass('calendarClosed');
		});
	});

	// Get the days of the month with ajax as not to reload the complete page
	$('#calendarMonthForm', this).retrieveDays();

	$('#calendarBlockHome, #calendarOuterWrap').each(processCalendar);
}

function processCalendar() {
	// If we have loaded new content in the calendar (that's when we call this function),
	// we actually want to show it as well.
	$('#calendarBlockHome').trigger('openCalendar').find('div.dayList:visible a.activeItem').trigger('showTooltip');
	
	// Let's make a little bit more fancy export options
	$('a.icalExport:not(.processed)', this).addClass('processed').click(icalExport);
	
	$('ul.calendarCategories a').each(function() {
		//console.log($.parseGetParameters($(this).attr('href')));										   
	});
	
	$('div.dayList:visible:not(.ajaxified)', this).addClass('ajaxified').each(function() {
		// Enable tooltips
		var days =  $('a', this).calendarTooltip(), settings;
		$('#tooltip').append('<div class="helper" />');
		
		settings = {
				target: $('div.calendar:visible'),
				workspace: $('#calendarWrap > div:visible'),
				processBackLinks: false,
				preload: false,
				dimensional: $('#calendarBlockHome').is('.calendarBlockDay'),
				createViewport: true,
				fixViewport: true,
				onShow: processCalendar,
				find: 'div.calendar',
				ajaxParams: {output: 'json', retrieve: 'content', element: 'calendar'},
				subMenu: 'ul.calendarCategories a',
				hash: true
			};
		if ($('#calendarBlockHome').is('.calendarBlockWeek')) settings.fx = {showViewport: 'slideDown', hideViewport: 'slideUp'};
		// Enable ajax navigation on the days
		days.ajaxNav(settings);
		setOma();
	});
	
	// Add nice hovers and ajax clicks
	$('ul.calendarDateList:not(.fancified)', this).addClass('fancified').each(processDateList);
	$('div.weekCalendar').processWeekCalendar();
	
	processEventDetails.apply(this);
}

$.fn.processWeekCalendar = function() {
	this.filter(':not(.fancified)').addClass('fancified').each(function() {
		var self = $(this), entries = self.find('div.weekEntry'), active = entries.filter('.eventOpen');
		entries.each(function() {
			var entry = $(this);
			entry
				.hoverClass('eventHover')
				.click(function(e) {
					active.trigger('foldClose');
					active = entry.trigger('foldOpen');
					e.preventDefault();
				}).bind('foldOpen', function() {
					entry.addClass('eventOpen').removeClass('eventClosed');
				}).bind('foldClose', function() {
					entry.addClass('eventClosed').removeClass('eventOpen');
				});
		});
	});
	return this;
};

function processDateList() {
	$('a.eventLink', this)
		.fancifyEventLink()
		.ajaxLoad({output: 'json', retrieve: 'content', element: 'eventdetails'}, {cache: true}, onAjaxLoad);
}

$.fn.fancifyEventLink = function() {
	if (!$.ie6()) {
		this.each(function() {
			var self = $(this), descr = $('span.description', self);
			if (self.is('.hover')) return;
			self.addClass('hover');
			if ($.browser.msie && $.browser.version < 8) {
				// z index problem forces us to raise the z index on hover
				var z = self.parent().andSelf().add(descr);
				self.hoverIntent(
					function() {
						z.css('zIndex', 10);
						descr.animate({opacity: 'show'}, 600);
					}, function() {
						descr.animate({opacity: 'hide'}, 300, function() { z.css('zIndex', 9); });
					}
				);		
			} else {
				self.hoverIntent(
					function() { descr.animate({opacity: 'show'}, 600); },
					function() { descr.animate({opacity: 'hide'}, 300); }
				);
			}
		});
	}
	return this;
};

function onAjaxLoad(json) {
	var wrapper = $('div.eventDetailsWrapper:not(:animated)');
	if (wrapper.length) wrapper.hide('fast', function() { $(this).remove(); });
	$('#calendarBlockHome').trigger('closeCalendar', function() {
		var content = $(json.content).find('div.eventDetailsWrapper').hide().insertAfter('#calendarBlockHome');
		$('img', content).imageReady(function() {
			processEventDetails.apply(content);
			content.show('slow');
		});
	});		
}

function icalExport(e) {
	var html, href = this.href, webcal = href.replace('http://', 'webcal://');
	html = [
		'<strong>Selecteer 1 van de onderstaande opties:</strong>',
		'<a class="icalDownload" href="' + href +  '">Download .ical bestand</a>',
		'<a class="icalSubscribe" href="' + webcal +  '">Abonneer met iCal of Outlook</a>'
	];
	PopupMessage().lightbox(html.join('<br>'), {width: 350});
	e.preventDefault();	
}

// Process the details of an event when it has been added to the page
function processEventDetails() {
	// Let's make a little bit more fancy export options
	$('a.icalExport:not(.processed)', this).addClass('processed').click(icalExport);
	// Add a shadow to the image in content
	$('span.ewyseImageInContent', this).shadow({imagePath: 'assets/images/shadow/content_image/', imageType: 'gif'});
	// Add a hover with a close button
	$('div.eventDetails:not(.processed)', this).addClass('processed').each(function() {
		var self = $(this), closeButton;
		closeButton = $('<span class="closeEventDetails">&nbsp;</span>')
			.appendTo(self)
			.click(function() {
				// Remove the details and show the calendar, if closed
				self.parent().hide('slow', function() {
					$('#calendarBlockHome').trigger('openCalendar');
					$(this).remove();
				});
			});
		// No opacity for IE.. it looks shitty in combination with PNG24
		$.browser.msie ? closeButton.hide() : closeButton.css({opacity: 0});
		self.hover(
			function() {
				self.addClass('detailsHover');
				$.browser.msie ? closeButton.show() : closeButton.stop().fadeTo(1500, 1);
			}, function() {
				$.browser.msie ? closeButton.hide() : closeButton.stop().fadeTo(500, 0);
				self.removeClass('detailsHover');
			}
		);
	});

	$('a.lightbox').lightbox({output: 'json', retrieve: 'content'}, {cache: true, onShow: processContent});
}

// This custom plugin retrieves the list of days when a new month is selected
$.fn.retrieveDays = function() {
	this.filter('form:not(.ajaxForm)').addClass('ajaxForm').each(function() {
		var self = $(this), options = {}, elSelect = self.find('#selectMonth'), current = elSelect.val(), stack = [], block = $('#calendarBlockHome');
		options[current] = self.next();
		
		// Wrap, so we can have some cool effects
		var wrapper = options[current].css({right: 0}).wrap('<div />').parent().css({overflow: 'hidden', height: 22, position: 'relative'});
		
		function checkElement(a, form, c) {
			var target = elSelect.val();
			if (current == target) return false;
			if (options[target]) {
				show(target);
				return false;
			} else stack.unshift(target);
			// Go ahead and submit the form
			return true;
		}
		
		function addContent(json) {
			var target = stack.pop();
			options[target] = $(json.content).find('div.dayList').css({right: -1000, display: 'none'}).appendTo(wrapper);
			// create an extra div for the ajaxnav to come
			$('#calendarWrap').append('<div/>');
			show(target, true);
			
		}
		
		function show(target, newContent) {
			var cur = options[current], tar = options[target], blockHeight = block.height();
			// Hide the viewport of the current active days (ajaxNav method)
			cur.find('> a:first').trigger('hideViewport');
			// Fix the block height, so it won't collapse when we hide the current content, but only if it's actually open right now
			if (blockHeight > 50) block.height(block.height());
			// Hide the tooltip
			$.calendarTooltip.hide.call($.calendarTooltip, function() {
				// hide the current days
				cur.animate({right: -1000}, 300, 'easeInOutCubic', function() {
					$(this).hide().css();
					// Show the new days
					tar.show().animate({right: 0}, 300, 'easeInOutCubic', function() {
						// Process the new content with ajax
						if (newContent) processCalendar.apply(block);
						setTimeout(function () {
							// Show the tooltip and the viewport of the ajaxnav
							tar.find('a.activeItem').trigger('showTooltip').trigger('showViewport');
							setTimeout(function() {
								block.css('height', '');
								// Open calendar
								block.trigger('openCalendar');
							}, 100);
						}, 100);
					});
				});
			}, 0);
			current = target;
		}
		
		self
			.args({output: 'json', retrieve: 'content', element: 'days'})
			.ajaxForm({dataType: 'json', beforeSubmit: checkElement, success: addContent});
	});
};

$.calendarTooltip = {
	tooltip: false,
	timer: false,
	context: false,
	status: 'hidden',
	
	init: function() {
		var self = this;
		if (!this.tooltip) {
			this.tooltip = $('<div class="resultsTooltip"><div class="resultsTooltipInner"><h3>&nbsp;</h3><div class="resultsTooltipHelper"></div></div></div>')
				.appendTo('div#calendarBlockHome');
			//this.tooltip.find('div.resultsTooltipHelper').ifixpng();
		}
	},
	
	clearTimer: function() {
		clearTimeout(this.timer);
		this.timer = false;
	},
	
	show: function(content, context, options) {
		var self = this, data, $context = $(context), left = $context.parent().parent().position().left + $context.parent().position().left + $context.position().left + $context.outerWidth() / 2 - this.tooltip.width() / 2;
		options = options || {};
		
		data = {
			content: content,
			context: context,
			animate: {height: 22, marginTop: 0}
		};
		
		this.clearTimer();
		if (this.status == 'show') {
			data.animate.left = left;
			this._show(options, data);
		} else if (this.status == 'active') {
			this.hide(function() {
				data.css = {left: left};
				this.timer = setTimeout(function() {
					self._show.call(self, options, data);
				}, 0);
			});
		} else {
			data.css = {left: left};
			this._show(options, data);
		}
	},
	
	_show: function(options, data) {
		var self = this;
		// For IE6 we don't have the q_shadow_inner element, so we need the second defined element instead
		var h3 = this.tooltip.css(data.css).find('h3').stop();
		if (h3.html() != data.content) {
			if (self.status == 'hidden') {
				h3.empty().html(data.content).css({opacity: 1});
			} else {
				h3.stop().animate({opacity: 0}, 'fast', function() {
					$(this).empty().html(data.content).animate({opacity: 1}, 'fast');
				});
			}
		} else h3.css({opacity: 1});
		this.status = options.status;
		this.tooltip.stop().animate(data.animate, 'normal', 'easeOutCubic');
	},
	
	hide: function(callback, time) {
		var self = this, animate = {height: 0, marginTop: 22};
		if (typeof time == 'undefined') time = 300;
		this.clearTimer();

		this.timer = setTimeout(function() { self.tooltip.stop().animate(animate, 'normal', 'easeOutCubic', function() {
			self.status = 'hidden';
			if (callback) callback.apply(self);
		}); }, time);
	}
};

$.fn.calendarTooltip = function() {
	$.calendarTooltip.init();
	var timeout;
	
	var items = this.filter(':not(.jq_tooltip)').addClass('jq_tooltip').each(processItem);
	
	function createContent(self) {
		var content = self.attr('title');
		self.removeAttr('title');
		return content;
	}
	
	function show(event) {
		var self = $(this), status = event.originalEvent ? 'show' : 'active';
		if (self.is('.activeItem') && $.calendarTooltip.status == 'active') {
			$.calendarTooltip.status = 'show';
			//return;
		}
		clearTimeout(timeout);
		if (!(content = self.data('content'))) self.data('content', createContent(self));
		$.calendarTooltip.show(self.data('content'), this, {status: status});
	}
	
	function processItem() {
		var self = $(this);
		self.hover(show, function() {
			if (self.is('.activeItem')) {
				timeout = setTimeout(function() {
					$.calendarTooltip.status = 'active';
				}, 10);
				return;
			}
			$.calendarTooltip.hide(function() {
				timeout = setTimeout(function() {
					items.filter('.activeItem').trigger('showTooltip');
				}, 100);
			});
		}).bind('showTooltip', show);
		if (self.is('.activeItem')) self.trigger('showTooltip');		
	}
	
	return this;
};

})(jQuery);