/*
	jQuery menu v1.31 alpha
	
	Wouter Beeftink
	wouter@footsteps.nl
*/

(function($) {

	$.fn.menu = function(options) {
	
		var opts = $.extend({
			item : 'li',
			init : null,
			subItem : 'ul',
			effect : 'default',
			min : 1,
			showSpeed : 200,
			showDelay : 0,
			showEasing : 0,
			hideSpeed : 200,
			hideDelay : 800,
			hideEasing : null,
			active : 'active',
			maxWidth : null
		}, options);
		
		var self = this,
			activeIndex;
			
		var delays = {
			show : null,
			hide : null
		};
		
		var init = {
			
			fade : function(obj) {
				obj.css('opacity', '0');
			},
			
			slideVertical : function(obj) {
				$.data(obj[0], 'height', obj.outerHeight());
				obj.height(0);
			},
			
			slideHorizontal : function(obj) {
				$.data(obj[0], 'width', obj.outerWidth());
				obj.width(0);
			}
			
		};
		
		var effects = {
		
			show : {
			
				'default' : function(obj) {
					obj.show();
				},
				
				fade : function(obj) {
					obj.show();
					obj.animate({
						opacity : 1
					}, opts.showSpeed, opts.showEasing);
				},
				
				slideVertical : function(obj) {
					obj.show();
					obj.animate({
						height : $.data(obj[0], 'height')
					}, opts.showSpeed, opts.showEasing);
				},
				
				slideHorizontal : function(obj) {
					obj.show();
					obj.animate({
						width : $.data(obj[0], 'width')
					}, opts.showSpeed, opts.showEasing);
				}
			
			},
			
			hide : {
			
				'default' : function(obj) {
					obj.hide();
				},
				
				fade : function(obj) {
					obj.animate({
						opacity : 0
					}, opts.hideSpeed, opts.hideEasing, function() {
						obj.hide();
					});
				},
				
				slideVertical : function(obj) {
					obj.animate({
						height : 0
					}, opts.showSpeed, opts.hideEasing, function() {
						obj.hide();
					});
				},
				
				slideHorizontal : function(obj) {
					obj.animate({
						width : 0
					}, opts.showSpeed, opts.hideEasing, function() {
						obj.hide();
					});
				}
				
			}
			
		};
		
		this.showItem = function(index) {
			toggleItem.call(this, 'show', index);
			return this;
		};
		
		this.hideItem = function(index) {
			toggleItem.call(this, 'hide', index);
			return this;
		};
		
		this.getItems = function() {
			return $(this).children(opts.item);
		};
		
		function toggleItem(type, index) {
			
			var	item = this.getItems().eq(index),
				subItem = item.children(opts.subItem);
				
			// Check if the subItem has to be shown and if there is a hide timeout running
			if(type == 'show' && delays.hide) {
				
				// Clear the hide timeout
				window.clearTimeout(delays.hide);
				delays[type] = null;
				
				// Hide any other opened subItem
				$.each(this.getItems(), function(subIndex) {
					if(index != subIndex ) {
						callEffect.call(self, 'hide', $(this).children(opts.subItem), index);
					};
				});
				
			};
				
			// Check if the subItem exists and if the subItem contains more children than set by opts.min
			if(subItem.length && subItem.children().length > opts.min) {
				
				// Toggle class if the buttons isn't active already as defined by activeIndex
				if(opts.active && index != activeIndex) {
					type == 'show' ? item.addClass(opts.active) : item.removeClass(opts.active);
				};
				
				// Stop any ongoing animations
				subItem.stop();
				
				// Toggle subItem with delay
				if(opts[type + 'Delay']) {
					
					// Clear ongoing delay
					if(delays[type]) {
						window.clearTimeout(delays[type]);
						delays[type] = null;
					};
					
					// Set up delay and toggle subItem
					delays[type] = window.setTimeout(function() {
						callEffect.call(self, type, subItem, index);
					}, opts[type + 'Delay']);
					
				// Toggle subItem without delay
				} else {
					callEffect.call(self, type, subItem, index);
				};
			
			};
			
		};
		
		function callEffect(type, obj, index) {
			
			// Support custom effects
			if($.isFunction(opts.effect[type])) {
				opts.effect[type].call(this, obj, index, opts.speed, opts.easing);
			
			// Default effects
			} else {
				effects[type][opts.effect].call(this, obj);
			};
			
			
		};
		
		return this.each(function(index) {
		
			var el = $(this),
				items = self.getItems();
			
			// Store the active index for later use
			if(opts.active) {
				activeIndex = items.index(items.filter('.' + opts.active));
			};
			
			items.each(function(index) {
				
				var item = $(this),
					subItem = item.children(opts.subItem);				
				
				/* if(index > 4) {	
					var extra = (index - 4) * 100;
					subItem.css('left' , '-' + extra + 'px');
				}; */
				
				// Check if the subItem exists and if the subItem contains more children than set by opts.min
				if(subItem.length && subItem.children().length > opts.min) {
					
					// Support custom init function, let the user set up initial styles per subItem
					if($.isFunction(opts.init)) {
						opts.init.call(this, subItem);
						
					// Default init function
					} else if(init[opts.effect]) {
						init[opts.effect].call(this, subItem);
					};
					
				};
				
				item.bind({
					
					mouseover : function() {
						self.showItem(index);
					},
					
					mouseout : function() {
						self.hideItem(index);
					}
					
				});
				
			});
		
		});
	
	};

})(jQuery);
