/**
 * @author mzander
 */
(function($){  

	$.fn.menu = function(settings) {
		
		var config = {
			selector: 		'a',
			attr:			'href',
			
			event:			'click',
					
			show_effect:	'fadeIn',
			show_duration:	500,
			hide_effect:	'fadeOut',		
			hide_duration:	500,
			
			over:		function() { $(this).addClass(classes.item_hover); },
			out:		function() { $(this).removeClass(classes.item_hover); },
			active:		function() { $(this).animate({ opacity: '0.1' }, config.show_duration); },
			inactive:	function() { $(this).animate({ opacity: '1.0' }, config.hide_duration); },
		};
		
		if(settings) $.extend(config, settings);		
		
		var internals = {
			current: 	null,
			next:		null,
			locked:		false,
			timeout:	null
		}
		
		var root_class = 'menu';
		var classes = {
			item:			root_class + '-item',
			item_active:	root_class + '-item-active',
			item_hover:		root_class + '-item-hover',
			content:		root_class + '-content',
			wspace:			' ',
			dot:			'.'
		};
		
		var fn = {
			filter:	function() {
				return $(this).attr(config.attr) && $(this).attr(config.attr).charAt(0) == '#' && $($(this).attr(config.attr)); 
			},
			replace: function(elem) {
				var item = $('<div />');
				item.attr('class', classes.item);
/**				if(elem.attr('id'))
					item.attr('id', elem.attr('id'));
				if(elem.attr('style'))
					item.attr('style', elem.attr('style'));*/
				item.html(elem.html());
				
				elem.replaceWith(item);
				
				return item;
			},
			bind: function(item, content) {
				if($.isFunction(config.over) && $.isFunction(config.out)) {
					item.hover(config.over, config.out);
				}

				if (config.active && config.inactive) {
					item.bind('active', config.active);
					item.bind('inactive', config.inactive);
				}
				
				if (config.event) {
					item.bind(config.event, function(event) {
						
						internals.next = {
							item: 		this,
							content: 	content
						};
						
						if (internals.current.item != this && !$(this).hasClass(classes.item_active)) {

							if (fn.try_lock()) {
								if(internals.timeout)
									internals.timeout = null;
								
								fn.toggle(internals.current, internals.next);
								internals.current = internals.next;
							}
							else {
								var self = this;
								
								if(internals.timeout)
									clearTimeout(internals.timeout);
									
								internals.timeout = setTimeout(function(){
									if (internals.next.item == self) {
										$(self).trigger(config.event);
										$(self).trigger('mouseout');
									}
								}, config.hide_duration + config.show_duration);
							}
						}
					});
				}
								
				content.addClass(classes.content);
				
				if (!internals.current) {
					item.addClass(classes.item_active);
					
					internals.current = {
						item: 		item,
						content: 	content
					};
				}
				else content.hide();
			},
			toggle:	function(curr, next) {
				$(curr.item).removeClass(classes.item_active);
				$(next.item).addClass(classes.item_active);

				$(curr.item).trigger('inactive');	
				$(next.item).trigger('active');
					
				if (config.hide_effect && config.hide_duration && config.show_effect && config.show_duration) { 
					$(curr.content)[config.hide_effect](config.hide_duration, function() {
						$(next.content)[config.show_effect](config.show_duration, function(){ fn.unlock(); });
					});
				}
			},
			try_lock: function() {
				if(!internals.locked) 
					return (internals.locked = true);
				return false; 
			},
			unlock:	function() { internals.locked = false; }
		};
		
		this.each(function() {
			var self = this;
			$(self).addClass(root_class);
			
			$(self).find(config.selector).filter(fn.filter).each(function() {
				var content = $($(this).attr(config.attr));
				var item = fn.replace($(this));
				fn.bind(item, content);
			});
		});
		return this;
	};

})(jQuery);
