/* ----------------------------------------------------------------------------
	Menu
	This collection of functions control all menus within the CMS
	The menus are:
		- Page Tree (use buildMenu)
		- Page Edit (use buildMenu)
		- CMS Navigation (use buildNav)
---------------------------------------------------------------------------- */
var DeepMenu;

Deepend.Menu = function () {
	// setup constants and variables
	var HTML_ELEMENT_DEEPEND = "cms-deepend";
	var HTML_ELEMENT_TREE = DeepTree.HTML_ELEMENT_TREE;
	var HTML_BODY = "body"; this.HTML_BODY = HTML_BODY;
	var HTML_ELEMENT_MENU = "menu"; this.HTML_ELEMENT_MENU = HTML_ELEMENT_MENU;
	var HTML_ELEMENT_MOVE = "move"; this.HTML_ELEMENT_MOVE = HTML_ELEMENT_MOVE;
	var HTML_ELEMENT_NAV = "cms-nav"; this.HTML_ELEMENT_NAV = HTML_ELEMENT_NAV;
	var CSS_CONTROL = "cms-control"; this.CSS_CONTROL = CSS_CONTROL;
	var CSS_PAGE = "cms-item"; this.CSS_PAGE = CSS_PAGE;
	
	var oEvent; this.oEvent = oEvent;
	var sSection; this.sSection = sSection;
	var bIsMove = false; this.bIsMove = bIsMove;
	var bTracePath = false; this.bTracePath = bTracePath;
	var eMove; this.eMove = eMove;
	var iMove; this.iMove = iMove;
	var iMoveTo; this.iMoveTo = iMoveTo;
	var sMoveType; this.sMoveType = sMoveType;
	var eDeepend; this.eDeepend; eDeepend;
	var eNavContainer; this.eNavContainer = eNavContainer;
	var bNavVisible; this.bNavVisible = false;
	
	// menu links will be passed from each namespace
	var oLinks; this.oLinks = oLinks;
	
	// loading nav links into this object for continual use
	var oNav; this.oNav = oNav;
	
	// loading nav config and styles in this object for continual use
	var oConfig; this.oConfig = oConfig;
	
	/*
	handleOnClick
	@oEvent: Automatically passed by the event.
	*/
	this.handleOnClick = function(oEvent) {
		this.oEvent = oEvent;
		if (!this.oEvent) this.oEvent = window.event;
		
		var sSourceElement = this.oEvent.srcElement; this.sSourceElement = sSourceElement;
		var sPattern = new RegExp(DeepEdit.REGEXP_MARKER_ID); this.sPattern = sPattern;
		
		// find the origin of the click
		var eParentNode;
		this.eParentNode = DeepMenu.findParentNode(this.oEvent.srcElement, "div");
		
		
		switch (this.sSourceElement.nodeName.toLowerCase()) {
			case "span":
				// mouse click on tree
				if (this.eParentNode.getAttribute("id") == HTML_ELEMENT_TREE) {
					DeepTree.sPageTitle = this.oEvent.srcElement.innerHTML;
					DeepMenu.buildMenu(this.oEvent);
				}
				break;
			case "div":
				DeepMenu.closeControl();
				// mouse click on marker
				if (sPattern.test(this.sSourceElement.getAttribute("id"))) {
					DeepEdit.oProperties = eval("({" + this.sSourceElement.getAttribute("id").replace(/LAYER-/, "") + "})");
					DeepEdit.sModuleTitle = this.oEvent.srcElement.getAttribute("title");
					DeepMenu.buildMenu(this.oEvent);
				}
				break;
			case "li":
				// mouse click on menu
				if (this.eParentNode.getAttribute("id") != HTML_ELEMENT_MENU) DeepMenu.closeControl();
				break;
			case "img":
				// mouse click on add content button
				if (this.sSourceElement.getAttribute("id"))
					if (this.sSourceElement.getAttribute("id").indexOf("add:") != -1) {
						DeepMenu.oEvent = this.oEvent;
						DeepEdit.sAdd = this.sSourceElement.getAttribute("id").toLowerCase();
						DeepEdit.buildContentControl();
					}
				break;
			default:
				// close all controls
				DeepMenu.closeControl();
		}
	};
	
	/*
	buildMenu
	@oEvent: Passed by handleOnClick function.
	*/
	this.buildMenu = function(oEvent) {
		this.oEvent = oEvent;
		DeepMenu.oEvent = this.oEvent;
		var eMenu; this.eMenu = eMenu;
		var eUL; this.eUL = eUL;
		var eLI; this.eLI = eLI;
		
		if (document.getElementById(HTML_ELEMENT_MENU))
			// menu already exists
			this.eMenu = document.getElementById(HTML_ELEMENT_MENU);
		else {
			// create menu
			this.eMenu = document.body.appendChild(document.createElement("div"));
			this.eMenu.setAttribute("id", HTML_ELEMENT_MENU);
			this.eMenu.className = CSS_CONTROL;
			
			if (!DeepMenu.bIsMove) {
				// build normal menu
				buildLink(this.eMenu, DeepMenu.oLinks);
				
				if (DeepMenu.sSection == "tree")
					DeepMenu.iMove = DeepMenu.findParentNode(this.oEvent.srcElement, "li").getAttribute("id");
				else
					DeepMenu.iMove = this.oEvent.srcElement.getAttribute("id");
			} else {
				DeepMenu.closeControl("0,1");
				
				// build move menu
				buildLink(this.eMenu, findMenu(DeepMenu.oLinks));
				
				if (DeepMenu.sSection == "tree")
					DeepMenu.iMoveTo = DeepMenu.findParentNode(this.oEvent.srcElement, "li").getAttribute("id");
				else
					DeepMenu.iMoveTo = this.oEvent.srcElement.getAttribute("id");
			}
		}
		
		// position of menu
		var oMousePosition = new DeepMenu.getMousePosition(this.oEvent, 0, 0);
		with (this.eMenu) {
			style.top = oMousePosition.Y;
			style.left = oMousePosition.X;
		}
		
		function buildLink(eDiv, oLinks) {
			this.eDiv = eDiv;
			this.oLinks = oLinks;
			var sAction; this.sAction = sAction;
			var eSource; this.eSource = eSource;
			var bProceed; this.bProceed = true;
			eUL = document.createElement("ul");
			eDiv.insertAdjacentElement("afterBegin", eUL);
			
			if (oEvent.srcElement.nodeName.toLowerCase() == "div")
				eSource = oEvent.srcElement;
			else
				eSource = DeepMenu.findParentNode(oEvent.srcElement, "li");
			
			for (var e in oLinks) {
				// edit page needs to enable and disable moving links dependant on position
				if (DeepMenu.sSection == "edit")
					switch (oLinks[e].title) {
						case "move above":
							if (!parseInt(DeepEdit.oProperties.move_up) || !parseInt(DeepEdit.oProperties.class_ui_place)) this.bProceed = false;
							break;
						case "move below":
							if (!parseInt(DeepEdit.oProperties.move_down) || !parseInt(DeepEdit.oProperties.class_ui_place)) this.bProceed = false;
					}
				
				if (this.bProceed) {
					this.eLI = eUL.appendChild(document.createElement("li"));
					this.sAction = oLinks[e].action;
					if (this.sAction)
						this.eLI.onclick = new Function("return " + this.sAction + ".call(this, '"
							+ eSource.getAttribute("id") + "', '"
							+ oLinks[e].params +"', '"
							+ oLinks[e].title + "')");
					this.eLI.innerHTML = oLinks[e].title;
				}
				
				this.bProceed = true;
			}
		};
		
		function findMenu() {
			for (var e in this.oLinks)
				if (this.oLinks[e].title == "move") return this.oLinks[e].children;
		};
	};
	
	/*
	Move
	@oEvent: Passed by runMove.
	*/
	this.Move = function(oEvent) {
		this.oEvent = oEvent;
		var oMousePosition = new DeepMenu.getMousePosition(oEvent, 0, 10);
		with (DeepMenu.eMove) {
			style.top = oMousePosition.Y;
			style.left = oMousePosition.X;
		}
	};
	
	/*
	closeMenu
	@aCloseType: Array of boolean values to assist in closing certain menus
	*/
	this.closeControl = function(aCloseType) {
		var bCloseAll; this.bCloseAll = (aCloseType) ? false : true;
		this.aCloseType = (aCloseType) ? aCloseType.split(",") : "1,1".split(",");
		var oControls = [
			{ "title": HTML_ELEMENT_MENU },
			{ "title": HTML_ELEMENT_MOVE }
		];
		this.oControls = oControls;
		
		var eControl; this.eControl = eControl;
		for (var e in this.oControls) {
			if (document.getElementById(this.oControls[e].title) && this.aCloseType[e] == "1") {
				this.eControl = document.getElementById(this.oControls[e].title);
				this.eControl.removeNode(true);
			}
		}
		
		if (this.bCloseAll)
			// remove mouseover event
			manageEvents("remove", document, "mousemove", DeepMenu.Move);
	};
	
	/*
	loadNav
	*/
	this.loadNav = function() {
		// check to see if we already have the xml in memory
		if (!DeepMenu.oNav) {
			DeepMenu.oNav = this.oLoader.responseXML.documentElement.selectSingleNode("/menu/pages");
			DeepMenu.oConfig = this.oLoader.responseXML.documentElement.selectSingleNode("/menu/config");
		}
		
		DeepMenu.eDeepend = document.getElementById(HTML_ELEMENT_DEEPEND);
		// IE can't handle the menu so don't show it.
		if (BrowserDetect.browser != "Explorer") {
			//manageEvents("add", DeepMenu.eDeepend, "mouseover", DeepMenu.captureNavEvent);
		}
		
		// add nav container to a global var
		DeepMenu.eNavContainer = document.getElementById(DeepMenu.HTML_ELEMENT_NAV);
		//DeepMenu.eNavContainer.style.width = document.body.clientWidth + "px";
		
		// set png style of container
		DeepStyle.setPNG(DeepMenu.eNavContainer, DeepMenu.selectTextNode(DeepMenu.oConfig.selectSingleNode("container/backgroundimage")));
		
		// IE can't handle the menu so don't show it.
		if (BrowserDetect.browser != "Explorer") {
			//manageEvents("add", DeepMenu.eNavContainer, "mouseover", DeepMenu.captureNavEvent);
			//manageEvents("add", DeepMenu.eDeepend, "click", DeepMenu.hideNav);
		}
		//manageEvents("add", DeepMenu.eNavContainer, "mouseout", DeepMenu.hideNav);
		
		/*
		 * TODO
		 * Add mouseout event to the body instead of the element. When you rolloff the element the body will capture the event.
		 */


		var oBody;
		oBody = document.body;
		//manageEvents("add", oBody, "mouseover", DeepMenu.hideNav);
	};
	
	/*
	captureEvent
	@oEvent: Passed by mouse events
	*/
	this.captureNavEvent = function(oEvent) {
		this.oEvent = oEvent;
		switch (this.oEvent.type.toLowerCase()) {
			case "mouseover":
				if (DeepMenu.findParentNode(this.oEvent.srcElement, "div")) DeepMenu.toggleNav();
				break;
			case "mouseout":
				DeepMenu.eNavContainer.appendChild(document.createTextNode(" " + this.oEvent.type + " = " + this.oEvent.srcElement + ", "));
				//alert(this.oEvent.srcElement);
		}
	};
	
	/*
	toggleNav
	*/
	this.toggleNav = function() {
		if (DeepMenu.bNavVisible) return;
		
		DeepMenu.eNavContainer.style.visibility = "visible";
		DeepMenu.buildNav(DeepMenu.oNav.childNodes);
		
		// bNavVisible stops the mouseover event firing on child elements
		DeepMenu.bNavVisible = true;
	};
	
	
	/*
	 * hideNav
	 */
	this.hideNav = function() {
		if (DeepMenu.bNavVisible) {
			DeepMenu.eNavContainer.style.visibility = "hidden";
			DeepMenu.bNavVisible = false;
		}
	};
	
	/*
	buildNav
	*/
	this.buildNav = function(ePages, sSource) {
		this.ePages = ePages;
		//if (sSource) trace("sSource = " + sSource + "<br>sSource.match = " + parseInt(sSource.match(/\d[0-9]*/g)));
		this.sSource = (sSource) ? parseInt(sSource.match(/\d[0-9]*/g)) : 1;
		var eNav; this.eNav = eNav;
		var iNavLength; this.iNavLength = iNavLength;
		var eUL; this.eUL = eUL;
		var eLI; this.eLI = eLI;
		var eText; this.eText = eText;
		var sXPath; this.sXPath = "";
		var pageID; this.pageID = pageID;
		
		// remove nav option if stepping back in the tree
		this.eNav = DeepMenu.eNavContainer.getElementsByTagName("ul");
		this.iNavLength = this.eNav.length;
		if (this.iNavLength > 1 && this.sSource < this.iNavLength)
			for (i = this.iNavLength; i > this.sSource; i--) {
				this.eNav[i - 1].removeNode(true);
				this.iNavLength += -1;
			}
		
		// add element and apply styles from config
		this.eUL = document.createElement("ul");
		DeepMenu.eNavContainer.appendChild(this.eUL);
		DeepStyle.setPNG(this.eUL, DeepMenu.selectTextNode(DeepMenu.oConfig.selectSingleNode("container/backgroundimage")));
		with (this.eUL) {
			setAttribute("id", "m" + (this.iNavLength + 1));
			style.width = DeepMenu.selectTextNode(DeepMenu.oConfig.selectSingleNode("nav/width"));
			style.color = DeepMenu.selectTextNode(DeepMenu.oConfig.selectSingleNode("nav/color"));
			style.border = DeepMenu.selectTextNode(DeepMenu.oConfig.selectSingleNode("nav/border"));
			style.margin = DeepMenu.selectTextNode(DeepMenu.oConfig.selectSingleNode("nav/margin"));
		}
		
		//if ePages is not an object, then find the reference via id
		if (!isNaN(parseInt(this.ePages))) {
			// create xml path string
			for (x = 1; x <= this.sSource; x++) {
				this.sXPath += "page";
				if (x < this.sSource && this.sSource > 1) this.sXPath += "/";
			}
			pageID = this.ePages;
			this.ePages = DeepMenu.oNav.selectSingleNode(this.sXPath + "[@id=" + this.ePages +"]").selectNodes("page");

		}
		
		//trace("sXPath: " + this.sXPath + "[@id=" + pageID +"]");
		
				
		var ePagesLength; this.ePagesLength = this.ePages.length;
		
		// loop through collection and write links
		for (i = 0; i < this.ePagesLength; i++) {
			if (this.ePages[i].nodeType == 1) {
				this.eLI = document.createElement("li");
				this.eUL.appendChild(this.eLI);
				this.eText = document.createTextNode(DeepMenu.selectTextNode(this.ePages[i].selectSingleNode("name")));
//					trace("path: " + DeepMenu.selectTextNode(this.ePages[i].selectSingleNode(this.sXPath + "[@id=" + this.ePages +"]").selectSingleNode("link")));
//					trace("------------");

				with (this.eLI) {
					appendChild(this.eText);
					id = this.ePages[i].getAttribute("id");
					style.padding = DeepMenu.selectTextNode(DeepMenu.oConfig.selectSingleNode("nav/padding"));
				}
				this.eLI.onmouseover = function() {
					this.style.color = "#000";
					this.style.backgroundColor = "#FFF";
					this.style.cursor = "pointer";
				};
				this.eLI.onmouseout = function() {
					this.style.color = "#FFF";
					this.style.backgroundColor = "transparent";
				};

				if (this.ePages[i].selectNodes("page").length)
					{
					//this.eLI.onclick = function() { DeepMenu.buildNav(this.id, this.parentNode.id); };
					this.eLI.onclick = new Function(" return DeepMenu.buildNav(this.id, this.parentNode.id);");
					}
				else {
					this.eLI.onclick = new Function("return window.location.href='" + DeepMenu.selectTextNode(this.ePages[i].selectSingleNode("link")) + "'");

					//trace("location.href=" + DeepMenu.selectTextNode(this.ePages[i].selectSingleNode("link")));

					}
				
				//trace(DeepMenu.selectTextNode(this.ePages[i].selectSingleNode("link")));
			}
		}
		
		if (this.sSource == 1) {
			//trace("sSource = " + this.sSource);
			DeepMenu.eNavContainer.style.paddingBottom = "25px";
			//DeepMenu.eNavContainer.style.height = (DeepMenu.eNavContainer.scrollHeight + parseInt(this.eUL.style.marginTop)) + "px";
		}
		//DeepMenu.iNavLevel += 1;
	};
	
	/*
	clearNav
	*/
	this.clearNav = function() {
		DeepMenu.eNavContainer.style.height = "25px";
		DeepMenu.bNavVisible = false;
		DeepMenu.iNavLevel = 1;
		
		//alert(DeepMenu.eNavContainer.childNodes[0].nodeName);
		//while (DeepMenu.eNavContainer.hasChildNodes)
		//	DeepMenu.eNavContainer.childNodes[0].removeNode(true);
	};
	
	/*
	getMousePosition
	@oEvent: Passed by buildMenu.
	*/
	this.getMousePosition = function(oEvent, iOffsetTop, iOffsetLeft) {
		this.oEvent = oEvent;
		this.X = (oBrowser.IE) ? (this.oEvent.clientX + document.documentElement.scrollLeft + iOffsetLeft) + "px" : (this.oEvent.pageX + iOffsetLeft) + "px";
		this.Y = (oBrowser.IE) ? (this.oEvent.clientY + document.documentElement.scrollTop + iOffsetTop) + "px" : (this.oEvent.pageY + iOffsetTop) + "px";
	};
	
	/*
	findParentTag
	@oEvent: Passed by handleOnClick.
	@sTag: This is tag name in which to find.
	*/
	this.findParentNode = function(eNode, sTag) {
		this.eNode = eNode;
		this.sTag = sTag.toLowerCase();
		
		// recurse back through the DOM
		if (!/html|body/.test(this.eNode.nodeName.toLowerCase())) {
			do { this.eNode = this.eNode.parentNode; }
			while ((this.eNode.nodeName.toLowerCase() != sTag) && (this.eNode.nodeName.toLowerCase() != "#document"));
		}
		return this.eNode;
	};
	
	/*
	selectTextNode
	@eElement: The element to start search
	*/
	this.selectTextNode = function(oElement) {
		this.oElement = oElement;
			do { this.oElement = this.oElement.firstChild; }
			while (this.oElement.nodeType != 3);
			return this.oElement.nodeValue;
	};
};
