/*
 * SooperFish 0.1
 * (c) 2010 Jurriaan Roelofs - SooperThemes.com
 * Inspired by Suckerfish, Superfish and Droppy
 * Licensed GPL: http://www.gnu.org/licenses/gpl.html
 */
$.fn.sooperfish = function(op) {

	var sf = $.fn.sooperfish;
	sf.o = [];
	sf.op = {};
	sf.c = {
		menuClass   : 'sf-js-enabled',
		isParent : 'sf-parent',
		arrowClass  : 'sf-arrow'
	};
	if ($.easing.swing && 0) { //set default easing
		sooperEasingShow = 'swing';
	} else {
		sooperEasingShow = 'linear';
	};
	if ($.easing.swing) {
		sooperEasingHide = 'swing';
	} else {
		sooperEasingHide = 'linear';
	};  
	sf.defaults = {
		multiColumn  : true,
		dualColumn  : 6, //if a submenu has at least this many items it will be divided in 2 columns
		tripleColumn  : 12, //if a submenu has at least this many items it will be divided in 3 columns
		hoverClass  : 'sfHover',
		delay    : 350, //make sure menus only disappear when intended, 500ms is advised by Jacob Nielsen
		showDelay   : 100, // Delay before show method is called
		animationShow  : {height:'show'},
		speedShow    : 100,
		easingShow      : sooperEasingShow,
		animationHide  : {height:'hide'},
		speedHide    : 175,
		easingHide      : sooperEasingHide,
		autoArrows  : false, //Adds span elements to parent li elements, projecting arrow images on these items to indicate submenus. I added an alternative image file with white arrows.
		onShow    : function(){}, //callback after showing menu
		onHide    : function(){}, //callback after hiding menu
		onHideStart : function(){} //callback before hiding menu
	};
	

	//Merge default settings with o function parameter
	var o = $.extend({},sf.defaults,op);
	var showing = false;
	var menuOpen = false;
	
	if (!o.sooperfishWidth) {
		o.sooperfishWidth = $('ul:first li:first', this).width(); //if no width is set in options try to read it from DOM
		//console.log($('ul:first li:first', this).html());
		//console.log(o.sooperfishWidth);
	} else {
		$('ul li', this).width(o.sooperfishWidth) //if width is set in invocation make sure this width is true for all submenus
	}

	this.each(function() {
		
		//Check dom for submenus
		var parentLi = $('li:has(ul)', this);
		parentLi.each(function(){
			if (o.autoArrows) { //Add autoArrows if requested
			$('>a',this).append('<span class="'+sf.c.arrowClass+'"></span>');
			}
			$(this).addClass(sf.c.isParent);
		});
		
		$('ul',this).css({left: 'auto',display: 'none'}); //The script needs to use display:none to make the hiding animation possible

		//Divide menu in columns
		//Set width override
		if (o.multiColumn) {
		var uls = $('ul',this);
		uls.each(function(){
			var ulsize = $('>li:not(.backLava)',this).length; //Skip list items added by Lavalamp plugin
			if (ulsize >= o.dualColumn) {
				if (ulsize >= o.tripleColumn) {
					$(this).width(3*o.sooperfishWidth);
				} else {
					$(this).width(2*o.sooperfishWidth);
				}
			}
		});
		}

		var root = this, zIndex = 1000;

		function getSubmenu(ele) {
			if (ele.nodeName.toLowerCase() == 'li') {
				var submenu = $('> ul', ele);
				return submenu.length ? submenu[0] : null;
			} else {
				return ele;
			}
		}

		function getActuator(ele) {
			if (ele.nodeName.toLowerCase() == 'ul') {
				return $(ele).parents('li')[0];
			} else {
				return ele;
			}
		}

		/// Hide menu - 
		function hideSooperfishUl() {
			var submenu = getSubmenu(this);
			if(!submenu) {
				var a = $("> a",$(getActuator(this)));
				turnOffActive(a);
			}
			if (!submenu || (showing && showing != submenu)) return;
			$.data(submenu, 'cancelHide', false);
			$.data(submenu, 'cancelShow', true);
			var t = setTimeout(function() {
				/// JEFF
				//o.onHideStart.call(submenu);
				
				hideNow(submenu);
			}, o.delay);
		}
		
		/// Hide menu immediately
		function hideNow(submenu) {
			if (!$.data(submenu, 'cancelHide')) {
				$(submenu).animate(o.animationHide,o.speedHide,o.easingHide,function(){ 
					o.onHide.call(submenu); 
					
					var a = $("> a",$(getActuator(submenu)));
					turnOffActive(a);
					
				});
			}
			return true;
		}
		
		
		function turnOffActive(mi) {
			var rel = mi.attr('rel');
			if(rel != '') {
				mi.removeClass(rel+'-active');
			}
		}
		
		function turnOnActive(mi) {
			var rel = mi.attr('rel');
			if(rel != '') {
				mi.addClass(rel+'-active');
			}
		}

		/// onHover for menu LIs
		function showSooperfishUl() {

			/// Prevent multiple from displaying at once...
			if(showing) {
				return;
			}
			
			var sfmenu = this;
			var a = $("> a",$(getActuator(sfmenu)));
			
			/// No menu?  Return...
			var submenu = getSubmenu(this);
			if (!submenu) {
				/// Show the background image
				turnOnActive(a);
				return;
			}
			
			/// Set some variables
			$(submenu).css({zIndex: zIndex++});
			$.data(submenu, 'cancelHide', true);
			$.data(submenu, 'cancelShow', false);
			
			/// If there's a menu open and it's not this one, let's hide it 
			/// right now so we can open up the new one and they don't overlap
			if(menuOpen && menuOpen != submenu) {
				$.data(menuOpen, 'cancelHide', false);
				hideNow(menuOpen);
				menuOpen = false;
			}
			
			/// Main routine to show menu after o.showDelay milliseconds
			setTimeout(function() {
				showing = submenu;
				menuOpen = submenu;
				if($.data(submenu, 'cancelShow')) {
					showing = false;
					return;
				}
				$(submenu).animate(o.animationShow,o.speedShow,o.easingShow,function(){ 
					showing = false;
					o.onShow.call(submenu); 
				});
				
				turnOnActive(a);
				
				if (sfmenu.nodeName.toLowerCase() == 'ul') {
					var li = getActuator(sfmenu);
					$(li).addClass('hover');
					$('> a', li).addClass('hover');
				}
			}, o.showDelay);
			
		}
		
		// Bind Events. Yes it's that simple!
		$('li', this).unbind().hover( showSooperfishUl, hideSooperfishUl);

	});

};

