//Menu Plugin - Version: 3.5
(function($){
	$.fn.menu = function(data,options) {
		var defaults = {
			direction:"down",
			currentL1:0,
			speed:500,
			closeDelay:100,
			openDelay:500,
			showL3s:true,
			reverseL2:true,
			debug:false
		};
		var dataStore = {
			currentActive:0,//currently active L1
			timeout:"",//the timout that hides the menus when a user rolls off them.
			L3Divs:0, //object of L3 Menus
			data:data
		};

		var options = $.extend(defaults, options);
				
		return this.each(function() {
			var menuid = $.getNextID();
			var $menuHolder = $(this);
			
			if(dataStore.data.length > 0){
				buildMenus();
			}else{
				if(options.debug){$.log("No Data to build the menu with");}
			}
			
			if(options.speed == 0){
				options.speed = 1;
			}
			
			function buildMenus(){				
				for(var a = 0; a < dataStore.data.length; a++){
					var $menuButton = $("#"+$menuHolder.attr("id")+"_"+dataStore.data[a].id);
							
					var L1id = dataStore.data[a].id;
					if(L1id == options.currentL1){
						$("#"+$menuHolder.attr("id")+"_"+L1id).addClass("on");
					}
					
					var $subMenu;
					var $linkHolder;
						
					if(dataStore.data[a].L2.length > 0){
						$menuHolder.after("<div id='L2"+menuid+"_"+L1id+"' class='submenu"+options.direction+"'></div>");
						$subMenu = $("#L2"+menuid+"_" + L1id);
						$linkHolder = $("<div class='link-holder'></div>");
						$subMenu.append($linkHolder);
						$subMenu.css("display","none");
						
						if(options.direction == "up" && options.reverseL2){						
							dataStore.data[a].L2.reverse();
						}
						
						for(var b = 0; b < dataStore.data[a].L2.length; b++){
							if(typeof dataStore.data[a].L2[b].url !== "undefined"){
								var target = dataStore.data[a].L2[b].target == true ? "_blank":"_self";
								var $aTag = $(document.createElement("a"))
										.addClass("subMenuItems"+options.direction)
										.attr("href", dataStore.data[a].L2[b].url)
										.attr("target",target)
										.attr("id","L2Item"+menuid+"_"+dataStore.data[a].L2[b].id)
										.append("<span>"+dataStore.data[a].L2[b].title+"</span>");
								
								$aTag.hover(function(){							
									//check for L3s
									var pageid = $(this).attr("id").split("_")[1];
									animateAllL3Out(pageid);
									if($("#L3"+menuid+"_"+pageid).length > 0){
										animateL3HolderIn(pageid);
									}
									
								},function(){
									//empty now, yay
								});
								//append new L2
								$linkHolder.append($aTag); 
								
								//L3s?
								if(dataStore.data[a].L2[b].L3.length > 0 && options.showL3s){
									var $L3Menu;
									$menuHolder.after("<div id='L3"+menuid+"_"+dataStore.data[a].L2[b].L3[0].parentid+"' class='L3Menu"+options.direction+"'></div>");
									$L3Menu = $("#L3"+menuid+"_" + dataStore.data[a].L2[b].L3[0].parentid);
									$L3Menu.css("display","none");
									for(var c = 0; c < dataStore.data[a].L2[b].L3.length; c++){
										if(typeof dataStore.data[a].L2[b].L3[c].url !== "undefined"){
											var target = dataStore.data[a].L2[b].L3[c].target == true ? "_blank":"_self";
											var $L3Tag = $(document.createElement("a"))
														.addClass("L3MenuItems"+options.direction)
														.attr("href", dataStore.data[a].L2[b].L3[c].url)
														.attr("target",target)
														.append("<span>"+dataStore.data[a].L2[b].L3[c].title+"</span>");
														
											$L3Tag.hover(function(){
												dataStore.currentActive = L1id;
								    			clearTimeout(dataStore.timeout);
								    			if(options.debug){$.log("CLEARED TIMEOUT");}
								    		},function(){
								    			dataStore.currentActive = 0;
								    			dataStore.timeout = setTimeout(function(){ animateAllOut()}, options.closeDelay);
								    			if(options.debug){$.log("L3 OUT!");}
								    		});
								    		$L3Menu.append($L3Tag);
										}
										
									}//end for loop L3s
									
									$L3Menu.prepend("<div id='L3menu-header'><!-- --></div>")
						    		.append("<div id='L3menu-footer'><!-- --></div>")
						    		.wrapInner("<div id='holder'></div>")
						    		.css("overflow","hidden");
									var $itemHolder = $L3Menu.children();
									
									$itemHolder.children().filter(function(){  
									    return $(this).attr("id") == "L3menu-header" || $(this).attr("id") == "L3menu-footer";
									})
									.hover(function(){
									    dataStore.currentActive = L1id;
									    clearTimeout(dataStore.timeout);
									},function(){
									    dataStore.currentActive = 0;
									    dataStore.timeout = setTimeout(function(){ animateAllOut()}, options.closeDelay);
									});
									
									$aTag.data("hasMenu",true).addClass("submenu");
									positionL3MenuHolder($L3Menu);
								}//end show L3s
							}//end L2 url check
						}//end for loop for L2s
																						
						var hOffset = (!isNaN(parseInt($menuButton.attr("hoffset")))) ? $menuButton.attr("hoffset") : 0;
						var vOffset = (!isNaN(parseInt($menuButton.attr("voffset")))) ? $menuButton.attr("voffset") : 0;

						$linkHolder.children(":first").addClass('first-link');
						$linkHolder.children(":last").addClass('last-link');
						
						$linkHolder.hover(function(){
							dataStore.currentActive = L1id;
							clearTimeout(dataStore.timeout);
						},function(){
						    dataStore.currentActive = 0;
						    dataStore.timeout = setTimeout(function(){ animateAllOut()}, options.closeDelay);
						    if(options.debug){$.log("L2 HOLDER OUT");}
						});
					
						$subMenu.prepend("<div id='menu-header'><!-- --></div>")
						    .append("<div id='menu-footer'><!-- --></div>")
						    .wrapInner("<div id='holder'></div>")
						    .css("overflow","hidden")
						    .data("hOffset",hOffset)
						    .data("vOffset",vOffset);
						
						var $itemHolder = $subMenu.children();
						
						$itemHolder.children().filter(function(){  
						    return $(this).attr("id") == "menu-header" || $(this).attr("id") == "menu-footer";
						}).hover(function(){
						    dataStore.currentActive = L1id;
						    clearTimeout(dataStore.timeout);
						},function(){
						    dataStore.currentActive = 0;
						    dataStore.timeout = setTimeout(function(){ animateAllOut()}, options.closeDelay);
						});
						
						var $tempMenuItems = $itemHolder.children().filter(function(){  
						    return $(this).attr("id") != "menu-header" || $(this).attr("id") != "menu-footer";
						});
						
						$tempMenuItems.filter("div:first").addClass("menufirst");							
						
						var mylength = $itemHolder.children().filter(function(){  
						    return $(this).attr("id") != "menu-header" || $(this).attr("id") != "menu-footer";
						}).length;
						
						$menuButton.data("hasMenu",true);
						positionSubMenuHolder($subMenu);
					}//end if hav L2s	
				}//end for loop for L1s
				
				//need this to happen after menu is written...
				buildMenuAction();
				dataStore.L3Divs = $(".L3Menu"+options.direction);
				//if horizontal, open current L2
				if(options.direction == "horizontal"){
				    $obj = $("#"+$menuHolder.attr("id")+"_"+options.currentL1);
				    if($obj.data("hasMenu")){
				    	var pageID =  $obj.data("pageID");
				    	animateSubMenuHolderIn(pageID);
				    }
				}
			}//end buildMenus()
						
			function buildMenuAction(){
				var $menuItems = $("#"+$menuHolder.attr("id")+" li a");
				$menuItems.each(function(){
					$obj = $(this);
					$obj.data("pageID",$(this).attr("id").substring($menuHolder.attr("id").length+1,$(this).attr("id").length));
				});
				
				$menuItems.hover(function () {
					killCurrentL2();
					
					var $obj = $(this);
					$obj.addClass("hover");
					if($obj.data("hasMenu")){
						var pageID =  $obj.data("pageID");
						dataStore.currentActive = pageID;
						dataStore.openTimeout = setTimeout(function(){animateSubMenuHolderIn(pageID);},options.openDelay);
						
						//animateSubMenuHolderIn(pageID);
					}
				}, 
				function () {
					var $obj = $(this);
					var pageID = $obj.data("pageID");
					
					clearTimeout(dataStore.openTimeout);
										
					if($obj.data("hasMenu")){
						dataStore.currentActive = 0;
						dataStore.timeout = setTimeout(function(){ animateAllOut()}, options.closeDelay);
					} else {
						$obj.removeClass("hover");
					}
					if(options.direction == "horizontal" && !$obj.data("hasMenu")){
						dataStore.timeout = setTimeout(function(){ animateAllOut()}, options.closeDelay);
					}
					
				});
				if(options.debug){$.log("Menu Actions Built");}
			}//end buildMenuAction
			
			/*-------------------ANIMATE ALL FUNCTIONS--------------------*/
			
			function killCurrentL2(){
				killAllL3Out();
				//dataStore.currentActive = 0;
				if(options.direction == "horizontal"){
					animateSubMenuHolderOut(options.currentL1);
				}
			}			
			
			function animateAllOut(){
				killAllL3Out();
				var $menuItems = $("#"+$menuHolder.attr("id")+" li a");
				$menuItems.each(function(){
					var pageid = $(this).attr("id").split("_")[1];
					if(pageid != dataStore.currentActive){
						animateSubMenuHolderOut(pageid);
					}
					
					if(options.direction == "horizontal" && (options.currentL1 == pageid && dataStore.currentActive == 0)){
						animateSubMenuHolderIn(options.currentL1);
					}
				});
			}
			
			function killAllL3Out(){
				$L3s = dataStore.L3Divs;
				$L3s.each(function(){
					var pageid = $(this).attr("id").split("_")[1];
					animateL3HolderOut(pageid,false);
				});
			}
			
			function animateAllL3Out(currentActiveL2){
				$L3s = dataStore.L3Divs;
				$L3s.each(function(){
					var pageid = $(this).attr("id").split("_")[1];					
					if(pageid != currentActiveL2)
						animateL3HolderOut(pageid);
				});
			}
			
			/*-------------------L2 FUNCTIONS--------------------*/
			
			function positionSubMenu($menuButton, $subMenu){
				var offset = $menuButton.getTopLeft();
				
				var top = 0;
				var left = 0;
				switch (options.direction){
				case "up":
					top = parseInt(offset.top) - parseInt($subMenu.height()) + parseInt($subMenu.data("vOffset"));
					left = parseInt(offset.left) + parseInt($subMenu.data("hOffset"));
					break;
				case "down":
					top = parseInt(offset.top) + $menuButton.height() + parseInt($subMenu.data("vOffset"));
					left = parseInt(offset.left) + parseInt($subMenu.data("hOffset"));	
					break;
				case "left":
					top = parseInt(offset.top) + parseInt($subMenu.data("vOffset"));
					left = parseInt(offset.left) - $subMenu.width() + parseInt($subMenu.data("hOffset"));
					//console.debug(left);
					break;
				case "right":
					top = parseInt(offset.top) + parseInt($subMenu.data("vOffset"));
					left = parseInt(offset.left) + $menuButton.width() + parseInt($subMenu.data("hOffset"));	
					break;
				case "horizontal":
					//set to the left positon of the main ul container
					var offset = $menuHolder.getTopLeft();
					top = parseInt(offset.top) + $menuHolder.height() + parseInt($subMenu.data("vOffset"));
					left = parseInt(offset.left) + parseInt($subMenu.data("hOffset"));
					break;
				default:
					top = parseInt(offset.top) + $menuButton.height() + parseInt($subMenu.data("vOffset"));
					left = parseInt(offset.left) + parseInt($subMenu.data("hOffset"));
					break;
				}
				$subMenu.css("top", top+"px");
				
				//console.debug(left);
				$subMenu.css("left", left+"px");
			}//end positionSubMenu
			
			function positionSubMenuHolder($subMenu){
				var top = 0;
				var left = 0;
				switch (options.direction){
					case "up":
						top = $subMenu.height();
						left = 0;
						break;
					case "down":
						top = $subMenu.height() * -1;
						left = 0;
						break;
					case "right":
						top = 0;
						left = 0 - $subMenu.width();
						break;
					case "left":
						top = 0;
						left = $subMenu.width();
						break;
					case "horizontal":
						top = $subMenu.height() * -1;
						left = 0;
						break;
					default:
						top = $subMenu.height() * -1;
						left = 0;
						break;
				}
				var $subMenuHolder = $subMenu.children("#holder");
				$subMenuHolder.css("top",top).css("left",left).css("position","relative");
			}//end positionSubMenuHolder			
						
			function animateSubMenuHolderIn(pageID) {
				if(options.debug){$.log("animate menu");}
				var $menuButton = $("#"+$menuHolder.attr("id")+"_"+pageID);
				var $subMenu =  $("#L2"+menuid+"_" + pageID);
				var $subHolder = $("#L2"+menuid+"_" + pageID+" div:first");
				var top = 0;
				var left = 0;
				
				if(options.debug){$.txt($subHolder);}
				positionSubMenu($menuButton, $subMenu);
				
				$menuButton.addClass("hover");
				$subHolder.queue("fx", []).stop();
				$subMenu.show().css("z-index",1000);
				if(options.debug){$.log("SPEED:" + options.speed);}
				//alert(options.direction);
				switch (options.direction){
					case "up":
						$subHolder.animate({top: 0},options.speed);
						break;
					case "down":
						$subHolder.animate({top: 0},options.speed);
						//$subHolder.css("top",0);
						break;
					case "left":
						$subHolder.animate({left: 0},options.speed);
						break;
					case "right":
						$subHolder.animate({left: 0},options.speed);
						break;
					case "horizontal":
						$subHolder.animate({top: 0},options.speed);
						break;
					default:
						$subHolder.animate({top: 0},options.speed);
						break;
				}
			}//end animateSubMenuHolderIn
			
			function animateSubMenuHolderOut(pageID) {
				//if(options.debug){$.log("animate OUT");}
				var $menuButton = $("#"+$menuHolder.attr("id")+"_"+pageID);
				var $subMenu =  $("#L2"+menuid+"_" + pageID);
				
				//if(options.debug){$.log("menuid:"+menuid);}
				//if(options.debug){$.log("#L2"+menuid+"_" + pageID+" #holder");}
				var $subHolder = $("#L2"+menuid+"_" + pageID+" div:first");
			//	if(options.debug){$.log($menuButton);}
				var top = 0;
				var left = 0;
				
				$menuButton.removeClass("hover");
				
				
				$subMenu.css("z-index",options.speed);
				$subHolder.queue("fx", []).stop();
				switch (options.direction){
					case "up":
						top = $subMenu.height();
						$subHolder.animate({top: top},options.speed);
					break;
					case "down":
						top = parseInt($subMenu.height()) * -1;
						$subHolder.animate({top: top},options.speed); 
						//if(options.debug){$.log("TOP: "+top);}
						//if(options.debug){$.log("object = "+$subHolder.attr("id"));}
						//$subHolder.css({"top":top + "px"});
					break;
					case "right":
						left = 0 - parseInt($subMenu.width());
						$subHolder.animate({left: left},options.speed);
					break;
					case "left":
						left = parseInt($subMenu.width()) * 2;
						$subHolder.animate({left: left},options.speed);
					break;
					case "horizontal":
						top = parseInt($subMenu.height()) * -1;
						$subHolder.animate({top: top},options.speed); 
						break;
					default:
						top = parseInt($subMenu.height()) * -1;
						$subHolder.animate({top: top},options.speed); 
						break;
			
				}
				
				$subHolder.queue(function () {
					$(this).parent().hide();
					$(this).dequeue();
				});
					
			}//end animateSubMenuHolderOut
			
			/*-------------------L3 FUNCTIONS--------------------*/
			
			function positionL3Menu($menuButton, $subMenu){
				var offset = $menuButton.getTopLeft();
				var parentOffset = $menuButton.parent().parent().parent();
				if(options.debug){$.log(parentOffset.top +" : "+offset.top);}
				var top = 0;
				var left = 0;
				//the only one done so far is down, up, and horizontal. right and left are very very wrong!
				switch (options.direction){
				case "up":
					top = parseInt(offset.top) + parseInt(parentOffset.css("top"));
					left = parseInt(offset.left) + parseInt(parentOffset.css("left")) + $menuButton.width();	
					break;
				case "down":
					top = parseInt(offset.top) + parseInt(parentOffset.css("top"));
					left = parseInt(offset.left) + parseInt(parentOffset.css("left")) + $menuButton.width();	
					break;
				case "left":
				case "right":			
					top = parseInt(offset.top) + parseInt(parentOffset.css("top"));
					left = parseInt(offset.left) + parseInt(parentOffset.css("left")) + $menuButton.width();	
					break;
				case "horizontal":
					top = parseInt(offset.top) + parseInt(parentOffset.css("top")) + $menuButton.height();
					left = parseInt(offset.left) + parseInt(parentOffset.css("left"));
					break;
				default:
					top = parseInt(offset.top) + parseInt(parentOffset.css("top"));
					left = parseInt(offset.left) + parseInt(parentOffset.css("left")) + $menuButton.width();
					break;
				}
				$subMenu.css("top", top+"px");
				$subMenu.css("left", left+"px");
			}//end positionL3Menu
			
			function positionL3MenuHolder($subMenu){
				var top = 0;
				var left = 0;
				switch (options.direction){
					case "up":
						top = 0;
						left = 0 - $subMenu.width();
						break;
					case "down":
						top = 0;
						left = 0 - $subMenu.width();
						break;
					case "right":
						top = 0;
						left = 0 - $subMenu.width();
						break;
					case "left":
						top = 0;
						left = $subMenu.width() * 2; 
						break;
					case "horizontal":
						top = $subMenu.height() * -1;
						left = 0;
						break;
					default:
						top = 0;
						left = 0 - $subMenu.width();
						break;
				}
				var $subMenuHolder = $subMenu.children("#holder");
				$subMenuHolder.css("top",top).css("left",left).css("position","relative");
			}//end positionL3MenuHolder
			
			function animateL3HolderIn(pageid){
				var $menuButton = $("#L2Item"+menuid+"_"+pageid);
				var $subMenu =  $("#L3"+menuid+"_" + pageid);
				var $subHolder = $("#L3"+menuid+"_" + pageid+" div:first");
				var top = 0;
				var left = 0;
				
				positionL3Menu($menuButton, $subMenu);
				
				$menuButton.addClass("on");
				$subHolder.queue("fx", []).stop();
				$subMenu.show().css("z-index",1000);
				switch (options.direction){
					case "up":
						$subHolder.animate({left: 0},options.speed);
						break;
					case "down":
						$subHolder.animate({left: 0},options.speed);
						break;
					case "left":
					case "right":
						$subHolder.animate({left: 0},options.speed);
						break;
					case "horizontal":
						$subHolder.animate({top: 0},options.speed);
						break;
					default:
						$subHolder.animate({left: 0},options.speed);
						break;
				}
			}//end animateL3HolderIn
			
			function animateL3HolderOut(pageid,animate){
				//checks to see if i need to animate the L3s or just hide them
				animate = typeof(animate) != 'undefined' ? animate : true;
								
				var $menuButton = $("#L2Item"+menuid+"_"+pageid);
				var $subMenu =  $("#L3"+menuid+"_" + pageid);
				var $subHolder = $("#L3"+menuid+"_" + pageid+" div:first");
				var top = 0;
				var left = 0;
				
				$menuButton.removeClass("on");
				$subMenu.css("z-index",options.speed);
				$subHolder.queue("fx", []).stop();
				switch (options.direction){
					case "up":		
						left = 0 - parseInt($subMenu.width());
						//figure out a cleaner way to do this....
						if(animate){
							$subHolder.animate({left: left},options.speed);
						}else{
							$subHolder.css("left",left+"px");
						}
						break;
					case "down": 
						left = 0 - parseInt($subMenu.width());
						//figure out a cleaner way to do this....
						if(animate){
							$subHolder.animate({left: left},options.speed);
						}else{
							$subHolder.css("left",left+"px");
						}
						break;
					case "right":
						left = 0 - parseInt($subMenu.width());
						//figure out a cleaner way to do this....
						if(animate){
							$subHolder.animate({left: left},options.speed);
						}else{
							$subHolder.css("left",left+"px");
						}
						break;
					case "left":
						left = parseInt($subMenu.width()) * 2;
						$subHolder.animate({left: left},options.speed);
						break;
					case "horizontal":
						top = parseInt($subMenu.height()) * -1;
						if(animate){
							$subHolder.animate({top: top},options.speed);
						}else{
							$subHolder.css("top",top+"px");
						}
						break;
					default:
						left = 0 - parseInt($subMenu.width());
						//figure out a cleaner way to do this....
						if(animate){
							$subHolder.animate({left: left},options.speed);
						}else{
							$subHolder.css("left",left+"px");
						}
						break;
			
				}
				$subHolder.queue(function () {
					$(this).parent().hide();
					$(this).dequeue();
				});	
			}//end animateL3HolderOut
			
		});//end return this.each function
	};//end menu function
	
	$.fn.menu.version = function(){
      	if(window.console){
      		console.debug("Menu Plugin, Version: 3.5");
      	}
    };
})(jQuery);

(function($){
	var count = 0;
	jQuery.getNextID = function() {
		return count++;
	};
})(jQuery);

jQuery.txt = function() {
	return this.each(function(){
		$.log(this);
	});
};

//for debug/log stuff
jQuery.log = function(message) {
 if(window.console){
 	var str = message;
    if( typeof(message) == 'object' ){
		str = '&lt;';
		//str += message.nodeName.toLowerCase();
		for( var i = 0; i < message.attributes.length; i++ ){
			str += ' ' + message.attributes[i].nodeName.toLowerCase() + '="' + message.attributes[i].nodeValue + '"';
		}
		str += '&gt;';
	}
	console.debug(str);
 }
};
