(function($, undefined) {
	
	$.fn.widgetloader = function(settings) {
		
		var $this = this,
			setup = {
				target_url      : '',
				animation_speed : 500,
				std_post_data   : {},
				classes         : {
					animation       : 'loading',
					collapseLink    : 'collapse-link',
					active          : 'active',
					container       : 'container',
					collapsed_state : 'collapsed',
					refresh         : 'refresh'
				},
				/*
				 * Schema: 
				 * {
				 * 		<widget_name> : {
				 * 			selector : <selector>,
				 * 			animate : true|false
				 * 		}
				 * }
				 */
				hover : {
					widget : {
						selector : '',
						animate  : false
					}
				},
				event_calendar : null,
				regex          : {
					year  : /\(year\)\/(\d+)/,
					month : /\(month\)\/(\d+)/
				},
				collapse_state : 'collapsing'
			},
			methods = {
				
				load : function(index) {

					if($this[index] == undefined) return;
					var $item = $($this[index]);

					if($item.hasClass('toload')) {
						
						$.post(
							setup.target_url,
							$.extend({}, setup.std_post_data, { widget : $item.attr('rel') }),
							function(html) {
								
								if(html === 'false') {
									methods.removeItem($item);
									return;
								}
								
								methods.killLoading($item);
								methods.show($item, html);
								methods.load(index+1);
								
							}						
						);

					} else {
						
						methods.afterAppend($item);
						methods.load(index+1);
						
					}

				},
				
				refresh : function($item, data) {
					
					if(data === undefined) data = {};
					
					methods.showReloading($item);
					$.post(
						setup.target_url,
						$.extend({}, setup.std_post_data, data, { widget : $item.attr('rel') }),
						function(html) {
							
							if(html === false) {
								methods.removeItem($item);
								return;
							}
							
							methods.renew($item, html);
							
						}
					);
					
				},
				
				removeItem : function($item) {

					$item.slideUp(setup.animation_speed, function() {
						$item.remove();
					});
					
				},
				
				show : function($item, html) {

					var $html = $(html);
					
					$html.css('display', 'none');
					$item.append($html);
					
					methods.afterAppend($item);
					
					$html.slideDown(setup.animation_speed);

				},
				
				renew : function($item, html) {
					
					var $old = $item.find('.'+setup.classes.container),
						$new = $(html);
					
					$new.css('display', 'none');
					$old.before($new);
					methods.cannotWait($item);
					
					$old.slideUp(setup.animation_speed, function() {
						$old.remove();
						methods.afterAppend($item);
					});
					$new.slideDown(setup.animation_speed);
					
				},
				
				killLoading : function($item) {

					if($item.hasClass(setup.classes.animation)) {
						$item.removeClass(setup.classes.animation);
					}
					$item.find('.'+setup.classes.animation).removeClass(setup.classes.animation);

				},
				
				showReloading : function($item) {
					
					var $refresh   = $item.find('.'+setup.classes.refresh),
						$container = $item.find('.'+setup.classes.container);
					
					$refresh.height($container.height());
					$refresh.width($container.width());
					$refresh.fadeIn(setup.animation_speed);
					
				},
				
				hideReloading : function($item) {
					
					$item.find('.'+setup.classes.refresh).fadeOut(setup.animation_speed);
					
				},
				
				afterAppend : function($item) {

					// methods.hover($item);
					methods.activateCollapseLink($item);
					methods.cannotWait($item);

				},
				
				cannotWait : function($item) {
					
					if($item.attr('rel') === 'event_calendar_summary') methods.calendar_summary_events($item);
					
				},
				
				activateCollapseLink : function($item) {

					var $collapseLink = $item.find('.'+setup.classes.collapseLink);

					if($.fn.collapse === undefined || $collapseLink.length === 0 || $item.data(setup.collapse_state) === true) return;

					$collapseLink.addClass(setup.classes.active);
					$item.collapse({
						selectors : {
							button    : '.'+setup.classes.collapseLink,
							container : '.'+setup.classes.container
						}
					});
					$item.data(setup.collapse_state, true);
					
				},
				
				hover : function($item) {
					
					if($.fn.highlighter === undefined || setup.hover[$item.attr('rel')] === undefined) return;

					var widget = $item.attr('rel');
					$item.find(
						setup.hover[widget].selector
					).highlighter({
						animate : setup.hover[widget].animate
					});

				},
				
				calendar_summary_events : function($item) {
					
					var $pager = $item.find('.'+setup.classes.container);
					
					// Wenn wir uns auf einem event_calendar befinden,
					// wird die AJAX-Geschichte gar nicht erst gestartet
					if($pager.data('pager')) return;
					
					methods.summary_hover($item);
					
					if($.browser.version == '7.0') return;
					
					$pager.data('pager', true);
					$item.find('.calendar_heading_nav a').click(function(event) {
						
						var $this = $(this),
							href  = $this.attr('href'),
							target_date = {
								year  : setup.regex.year.exec(href)[1],
								month : setup.regex.month.exec(href)[1],
								day   : 0
						};
						
						if($this.data('clicked')) return;
						$this.data('clicked', true);
						
						methods.refresh($item, { current_date : target_date });
						event.preventDefault();
						
					});
					
				},
				
				summary_hover : function($item) {
					
					var $days = $item.find('.daylink'),
						animation_speed = setup.animation_speed / 2
						hoverDimensions = [];
					
					$days.each(function(index) {
						
						var $this  = $(this),
							$hover = $this.next('.program-hover');
							
						$hover.css({
							visibility : 'hidden', 
							display    : 'block'
						});
						var height = $hover.height(),
							width  = $hover.width();
						// JS ist schneller als die Renderengine!
						hoverDimensions[index] = setInterval(function() {
							height = $hover.height();
							width  = $hover.width();
							if(height > 0) {
								clearInterval(hoverDimensions[index]);
								$hover.css({
									visibility : 'visible',
									display    : 'none'
								});
							}
						},10);

						$this.mousemove(function(mouse) {
							$hover.offset({
								left : mouse.pageX-width-10,
								top  : mouse.pageY-height-10
							});
						});
						
						$this.hover(
							function() {
								$hover.css('opacity', 0);
								$hover.show();
								$hover.stop().animate({
									opacity: 1
								}, animation_speed);
							}, 
							function() {
								$hover.stop().animate({
									opacity: 0
								}, animation_speed);
								$hover.hide();
							}
						);
						
					});
					
				}
				
			};
			
		$.extend(true, setup, settings);
			
		methods.load(0);
		
	}
	
})(jQuery);

jQuery(document).ready(function($, undefined) {
	
	if(typeof current_date  === 'undefined') current_date  = false;
	
	$('.widget').widgetloader({
		target_url : (siteaccess === '/' ? '' : siteaccess)+'/rjax/widget/read',
		std_post_data : {
			node_id       : typeof calendar_node_id === 'undefined' ? node_id : calendar_node_id,
			root_node     : root_node,
			current_date  : current_date
		},
		hover : {
			event_calendar_program : {
				selector : 'a.event',
				animate : false
			}
		}
	});
	
});
