;(function($) {

	var Menus = function(selector, options) {
		var self = this;
		options = options || {};
		options.attach = $(options.attach) || $('body');
		options.hover = options.hover || 'hover';
		options.active = options.active || 'active';
		options.timeout = options.timeout || 250;
		options.liSelector = options.liSelector || 'li';
		options.addClickActions = true;
		this._timer = null;
		
		var is_msie8_or_lower = $.browser.msie && parseInt($.browser.version.substr(0,1)) <= 8;
		var jq_visible = function(selector, context) {
			if (is_msie8_or_lower) {
				var result = $();
				$(selector, context).each(function() {
					if ($(this).css('display') != 'none') {
						result = result.add($(this));
					}
				});
				return result;
			} else {
				return $(selector + ':visible', context);
			}
		};

		this._updateMenus = function() {
			var itemActive = $('> ' + options.liSelector + '.active',selector).size() > 0;
			if(itemActive) {
				this._setTimeOut();
			} else {
				this._updateWaitOver();
			}
		};
		
		this._setTimeOut = function() {
			if(this._timer)
				this._clearTimeOut();
			this._timer = setTimeout(function(){
				self._timer = null;
				self._updateWaitOver();
			}, options.timeout);
		};
		
		this._clearTimeOut = function() {
			if(this._timer) {
				clearTimeout(this._timer);
				this._timer = null;
			}
		};
		
		this._updateWaitOver = function() {
			if(this._hide())
				this._show();
		};

		var jq_isVisible = function(jq) {
			if (is_msie8_or_lower) {
				return jq.css('display') != 'none';
			} else {
				return jq.is(':visible');
			}
		};
		
		this._show = function() {
			var showing = $('li.'+options.hover, selector);
			if(showing.size() > 1)
				console.log('showing selector has too manythings in it');
			if(showing.size() == 0 && options.onHideAll)
				options.onHideAll();
			showing.first().each(function() {
				if(jq_isVisible($(this).data('menu')))
					return;
				$(this).data('menu').show();
				$(this).addClass(options.active);
				if(options.onShow)
					options.onShow($(this), $(this).data('menu'));
			});
		};

		var jq_noHoverClass = function(context, hoverClass) {
			if (is_msie8_or_lower) {
				var result = $();
				$('li', context).each(function() {
					if (!$(this).hasClass(hoverClass)) {
						result = result.add(this);
					}
				});
				return result;
			} else {
				return $('li:not(li.' + hoverClass + ')', context);
			}
		};
		
		this._hide = function() {
			var subHover = false;
			jq_noHoverClass(selector, options.hover).each(function() {
				var menu = $(this).data('menu');
				if($('li.'+options.hover,menu).size() > 0 ) {
					subHover = true;
					return; // we didn't hide becase the sub nav was highlighted
				}
				if(menu)
					menu.hide();
				$(this).removeClass(options.active);
			});
			return !subHover; // if not subHover, then we hid something
		};


		$(options.liSelector,selector).hover(function(){
			$(this).addClass(options.hover);
			self._updateMenus();
		}, function() {
			$(this).removeClass(options.hover);
			self._updateMenus();
		});
		$('> ' + options.liSelector,selector).each(function(){
			var menu = $('ul', this);
			var li = $(this);
			menu.hide();
			menu.detach();
			options.attach.append(menu);
			menu.css({
				'position': 'absolute',
				'top': li.position().top,
				'left': li.position().left + li.outerWidth(true)
			});
			menu.addClass('sub');
			$(this).data('menu', menu);
		});
		$('ul.sub ' + options.liSelector + ' > a',options.attach).each(function() {
			var href = $(this).attr('href');
			$(this).parent().click( function() {
				document.location = href;
			});
			$(this).parent().css('cursor','pointer');
			$(this).parent().hover(function(){$('a',this).toggleClass('hover');});
		});
	};

	// assume selector contains li elments
	$.fn.submenus = function(options) {
		var menus = new Menus(this, options);
		return this;		
	};
})(jQuery);

