/**
 * Delay function.
 */
Function.prototype.later = function(ms,s) {
	
	var sf = this,
	f = function() {
		var a = f.arguments,
		lf = function() {
			sf.apply(s,a);
		};
		setTimeout(lf,ms);
	};
	return f;
};

$(function() {

/**
 * search classes 'smartMenu' in a documents.
 */
$(".smartMenu").each(function() {
	
	// clear all contents.
	this.innerHTML = "";
	
	var menu = $(this),
		menuId = menu.attr("id"),
		imageDir = menu.attr("imageDir"),
		xmlDir = menu.attr("xmlDir"),
		slideSpeed = menu.attr("slideSpeed"),
		openAfter = menu.attr("openAfter"),
		debug = (String(menu.attr("debug")).toLowerCase() == "true"),
		file = ((xmlDir) ? xmlDir : "/shared/xml/") + menuId + ".xml",
		d = {
			imageDir: (imageDir) ? imageDir : "/images/menuR/",
			slideSpeed: (slideSpeed) ? slideSpeed : 200,
			openAfter: (openAfter) ?  openAfter : 1,
			debug: debug
		};
	
	// set default value per each menu.
	menu.data("default", d);
	
	// set selected item if specify.
	menu.data("select", menu.attr("select"));
	
	if (!menuId) {
		alert("Error: There is no id in the smartMenu.");
		return;
	}
	
	// load xml file.
	$.ajax({
		url: file,
		type: "GET",
		dataType: "xml",
		error: function() {
			alert("Error: fail to open file '" + file + "'.");
		},
		success: function(xml) {
			createItem({
				xml: $(xml).find("menu"),
				node: menu,
				depth: 1,
				menu: menu,
				parent: null
			});
		}
	});
});

/**
 * Create menu item.
 * @param {Object} obj
 */
function createItem(obj) {
	
	var xml = obj.xml,
		node = obj.node,
		depth = obj.depth,
		menu = obj.menu,
		parent = obj.parent,
		d = menu.data("default");
	
	$(xml)
		.children("item")
		.each(function() {
			
			var id = $(this).attr("id"),
				url = $(this).attr("url"),
				target = $(this).attr("target"),
				alt = $(this).attr("alt") || "",
				isSelected = (menu.data("select") == id),
				open = $(this).attr("open");
			
			open = !!(open && open.toLowerCase() == "true");
			
			if (!id) {
				alert("Error: There is no id in <item> of smartMenu.");
				return;
			}
			
			// create a item.
			var imageName = "menuR_" + id,
				item = $(
				"<div class='smartMenuItem' id='smartMenuItem-" + id + "'>" +
				"<img " +
				"class='smartMenuItemImage smartMenuItemImageDepth" + depth + "' " +
				"src='" + d.imageDir + imageName +
				(isSelected ? "_select" : "") + ".gif' alt='" + alt + "'/>" +
				"<img " +
				"class='smartMenuOpener smartMenuOpenerDepth" + depth +"' " +
				"src='" + d.imageDir + "arrow_open.gif" + "' />" +
				((d.debug) ?
					"<div>alt='" + alt + "'</div>" +
					"<div class='smartMenuDebugFont'>" +
						d.imageDir + imageName + ".gif</div>" :
					"") +
				"<div class='smartMenuChildrenPanel'></div>" +
				"</div>"
				),
				image = item.children(".smartMenuItemImage"),
				opener = item.children(".smartMenuOpener");
				cp = item.children(".smartMenuChildrenPanel");
			
			// setup item.
			item.data("menu", menu);
			item.data("parent", parent);
			item.data("opener", opener);
			item.data("id", id);
			item.data("url", url);
			item.data("target", target);
			item.data("imageName", imageName);
			item.data("image", image);
			item.data("isOpen", false);
			image.data("item", item);
			
			// change view when debug mode.
			if (d.debug) {
				item.css("border", "solid 1px #ff0000");
				item.css("line-height", "20px");
			}
			
			// append item node to parent node.
			node.append(item);
			
			// action of rollover and rollout.
			image.hover(
			
				// rollover.
				function(e) {
					
					if (menu.data("select") == id) return;
					
					image.attr(
						"src",
						d.imageDir + $(this)
							.data("item")
							.data("imageName") + "_over.gif"
					);
				},
				
				// rollout.
				function(e) {
					
					if (menu.data("select") == id) return;
					
					image.attr(
						"src",
						d.imageDir + $(this)
							.data("item")
							.data("imageName") +
								(item.data("isOpen") ?
									"_open" :
									"") +
								".gif"
					);
				}
			);
			
			// action of click.
			item.click(function(e) {
				
				e.stopPropagation();
				
				// select item.
				selectItem($(this));
			});
			
			// setup opener.
			var hasChild = ($(this).children("item").size() > 0);
			if (!hasChild) { opener.hide(); }
			
			// action of opener click.
			opener.click(function(e) {
				
				e.stopPropagation();
				
				openItem(item, !item.data("isOpen"));
			});
			
			// create child items.
			createItem({
				xml: this,
				node: cp,
				depth: depth + 1,
				menu: menu,
				parent: item
			});
			
			// update open status.
			openItem(item, open);
		});
	
	// call once after creation of all items.
	if (depth == 1) {
		
		// open item at begining.
		openItem.later(d.openAfter * 1000, this)(
			$("#smartMenuItem-" + menu.data("select")).data("parent"),
			true
		);
	}
}

/**
 * Open menu item.
 * @param {Object} item item of jquery object
 * @param {Boolean} status true:open, false:close
 * @param {Boolean} cancelAnim
 */
function openItem(item, status, cancelAnim) {
	
	if (!item) return;
	
	var menu = item.data("menu"),
		id = item.data("id"),
		d = menu.data("default"),
		image = item.data("image"),
		opener = item.data("opener"),
		cp = item.children(".smartMenuChildrenPanel"),
		s1 = item.data("isOpen"),
		s2,
		imageName,
		img,
		br = jQuery.browser;
	
	// open item.
	if (status) {
		if (s1) return;
		
		(cancelAnim) ?
			cp.show() :
			cp.slideDown(d.slideSpeed);
		
		s2 = true;
		imageName = "menuR_" + id + "_open";
		img = "arrow_close.gif";
		
		// IE6 has a bug HTML element disappear after animation.
		// This code prevent you from that bug.
		if (br.msie && br.version == "6.0") {
			var c = 0,
				t = setInterval(function() {
					cp.css("display", "none");
					cp.css("display", "block");
					c++;
					if (c > d.slideSpeed / 10) {
						clearInterval(t);
					}
				}, 10);
		}
		
	// close item
	} else {
		if (!s1) return;
		
		(cancelAnim) ?
			cp.hide() :
			cp.slideUp(d.slideSpeed);
		
		s2 = false;
		imageName = "menuR_" + id;
		img = "arrow_open.gif";
	}
	
	item.data("isOpen", s2);
	image.attr("src", d.imageDir + imageName + ".gif");
	opener.attr("src", d.imageDir + img);
}

/**
 * Select item.
 * @param {Object} item item of jquery object
 */
function selectItem(item) {
	
	var id = item.data("id"),
		menu = item.data("menu"),
		url = item.data("url"),
		target = item.data("target"),
		obj = $("#" + id),
		d = menu.data("default"),
		image = item.children(".smartMenuItemImage"),
		prevId = menu.data("select"),
		prev;
	
	// return if already selected.
	if (prevId == id) return;
	
	// change image to select one.
	image.attr(
		"src",
		d.imageDir + item.data("imageName") + "_select.gif"
	);
	
	// remove previous selected one.
	if (prevId) {
		prev = $("#smartMenuItem-" + prevId);
		if (prev.length) {
			prev.data("image")
				.attr("src", d.imageDir + prev.data("imageName") + ".gif");
		}
	}
	
	// keep selected id.
	menu.data("select", id);
	
	if (url) {
		if (target) {
			window.open(url, target);
		} else {
			location.href = url;
		}
	} else if (obj.length) {
		$.scrollTo(obj, { speed:500, axis:'y' } );
	} else {
		alert("no target of id:'" + id + "' in this page.");
	}
}

});

/*

[XML object]

 <menu>
   <item id="" url="">
     <item id="" url=""></item>
   </item>
 </menu>

[jquery object] ... these value is get by jquery.data() method.

 menu.default
 menu.select

 item.menu
 item.id
 item.url
 item.imageName
 item.isOpen
 item.image
 item.parent
 item.opener
 
 image.item

*/

