(function($) {
	//
	// plugin definition
	//
	$.fn.xmlmenu = function(options) {
		var opts = $.extend({}, $.fn.xmlmenu.defaults, options);
		
		return this.each(function() {
			var $this = $(this);
			var containerCount = 0;
			var hoverCounter = 0;
			var itemPath = [];
			var timeOut;
			
			$this
				//.append("<div class='xmlmenu-header'></div>")
				.html("<div class='xmlmenu-content'></div>");
			//var $header = $this.find("div:first");
			var $content = $this.find("div:last");
			
			var items = []; 
				
			$.get(opts.xml,opts.postVariables,function(r){
				processData(r);
				
				for (i=0;i<items.length;i++){
					var $item = $content.append(markupMenuItem(items[i],"xmlmenu-content-item")+"<div class='xmlmenu-content-divider'></div>")
						.find('.xmlmenu-content-item:last')
						.data("level",0)
						.data("parents",[])
						.data("posInArray",i)
						.data("children",items[i].children)
						.click(function(){
								var lnk = $(this).find("a").attr("href");
								if (lnk!="") window.open(lnk,"_self");
							})
						.hover(function(){
							hoverInHandler();
							showSubMenu($(this));
						},function(){
						 	hoverOutHandler();
						})
					if (items[i].children.length>0)
						$item.addClass("xmlmenu-content-item-children");
				}
				
				$(".xmlmenu-content-divider").html("");
				
				if (typeof opts.menuReady == "function")
					opts.menuReady();
				
			});
			
			function showSubMenu($me){
				var level = $me.data("level");
				var children = $me.data("children");
				var offset = $me.offset();
				var width = $me.width()
								+parseInt($me.css("paddingLeft").replace("px",""))
								+parseInt($me.css("paddingRight").replace("px",""));
				var height = $me.height()
								+parseInt($me.css("paddingTop").replace("px",""))
								+parseInt($me.css("paddingBottom").replace("px",""));
				
				while (itemPath.length > level){
					itemPath.pop();
				}
				itemPath[level] =$me.data("posInArray");
				
				
				if ($me.is('.xmlmenu-content-item')){
					$me.parent().find(".xmlmenu-content-item").removeClass("xmlmenu-content-item-active");
					$me.addClass("xmlmenu-content-item-active");
				} else {
					$me.parent().find(".xmlmenu-container-item").removeClass("xmlmenu-container-item-active");
					$me.addClass("xmlmenu-container-item-active");
				}
				
				updateContainers(level+1,(children.length>0));
				
				
				if (children.length>0){
				
					var $activeCont = $('body').find(".xmlmenu-container:last");	
										
					if (level==0)
						var offtop=offset.top; else var offtop=offset.top-1;
										
					$activeCont.html("");
							
					for (i=0;i<children.length;i++){
						var $activeItem = $activeCont.append(markupMenuItem(children[i],"xmlmenu-container-item")).children(".xmlmenu-container-item:last");
						
						$activeItem.data("level",level+1)
							.data("children",children[i].children)
							.data("posInArray",i)
							.click(function(){
								var lnk = $(this).find("a").attr("href");
								if (lnk!="") window.open(lnk,"_self");
							})
							.hover(function(e){
								showSubMenu($(this));
							},function(){
							});
						
						if (i+1<children.length)
							$activeItem.addClass("xmlmenu-container-item-border");
							//$activeCont.append("<div class='xmlmenu-container-divider'>");
					}
					
					var contheight = $activeCont.height();					
					
					
					var top = parseInt(offtop-contheight/2+height/2+0.5);
										
					$activeCont.css({top:top, left:(offset.left+width)});
					if(top<0)
						top=0;

				}
			}
			
			function updateContainers (level,children) { //add or remove
				var countIs = $('body').find(".xmlmenu-container").length;
				
				if (children){
					var countShouldBe = level;
				} else {
					var countShouldBe = level-1;
				}
				
				
				if (countIs<countShouldBe){
					$('body').append("<div class='xmlmenu-container'>").find(".xmlmenu-container:last")
							.hover(function(){
								hoverInHandler();
							},function(){
								hoverOutHandler();
							}).css({zIndex:countIs+1+100, position:"absolute"});
				} else if (countIs>countShouldBe) {
					$(".xmlmenu-container:gt("+(countShouldBe)+")").remove();
					$(".xmlmenu-container:eq("+(countShouldBe)+")").remove();
				}
			}
			
			function hoverOutHandler(){
				hoverCounter--;
				timeOut = setTimeout(function () {
									itemPath = [];
									$(".xmlmenu-content-item").removeClass("xmlmenu-content-item-active");
									updateContainers(1,false);	
								},1000);
			}
			
			function hoverInHandler(){
				hoverCounter++;
				if (timeOut){
					clearTimeout(timeOut);
					timeOut = false;
				}
			}
			
			
			function markupMenuItem(item,cssClass){
				var markup;
				markup = "<div class='"+cssClass+"'>";
								
				if (item.link!=""){
					markup+="<a href='"+item.link.replace("%22",'"')+"'"+((item.id!="") ? " id='"+item.id+"'" : "")+">"+item.title+"</a>";
				} else {
					markup+="<span"+((item.id!="") ? " id='"+item.id+"'" : "")+">"+item.title+"</span>";
				}
				
				if (item.icon!="") {
					markup+="<div class='xmlmenu-content-icon'><img src='"+item.icon+"'></div>";
				}
				
				markup+="</div>";
				return markup;
			}
			
			function processData(r){
				var $r = $(r);				
				items = recursiveProcess($r.children("menu").children("item"));
				
				function recursiveProcess(itembranch){
					var arr = [];
					var children = itembranch;
					
					children.each(function(){
						var obj = {};
						obj.title=$(this).attr("title");
						obj.link=$(this).attr("link") || "";
						obj.icon=$(this).attr("icon") || "";
						obj.id=$(this).attr("id") || "";
						if ($(this).children("item").length>0)
							obj.children = recursiveProcess($(this).children("item")); else obj.children={};
						arr.push(obj);
					});
										
					return arr;
				}
								
			}

			
		});
	};
	
	//
	// private functions
	//

	//
	// public functions
	//
	
	//
	// plugin defaults
	//
	$.fn.xmlmenu.defaults = {
		url: "",
		postVariables:{},
		
		//callbacks
		menuReady:""
	};
})(jQuery);
