// $Id$

/*
	Copyright 2006 Mike Davis - LookHere Multimedia Design
	www.lookhere.co.za
	mike@lookhere.co.za
*/

var LookhereMenu = Class.create();

LookhereMenu.prototype = {
	initialize: function(rootElementName) {
		var rootElement = $(rootElementName);
		var rootMenu = new LookhereMenuEntry(null, rootElement);
		
		rootMenu._apply_style_to_children();
		rootMenu._calculate_sizing();
		rootMenu._calculate_adjustments();
		rootMenu._align_children();
		rootMenu._resize_children();

		for(var childIndex  = 0; childIndex < rootMenu.children.length; childIndex++) {
			var childMenu = rootMenu.children[childIndex];
			childMenu.hideChildren();
		}
		
		this._rootMenu = rootMenu;
	},
	showChildren: function() {
		this._rootMenu.showChildren();
	}
};

var LookhereMenuEntry = Class.create();

LookhereMenuEntry.prototype = {
	initialize: function(parentMenu, myElement)  {
		this.myElement = $(myElement);
		if(!this.myElement) {
			this._debug('error - no myElement');
			return;
		}

		this.parentMenu = parentMenu;
		
		// vertical (0) or horizontal (1)?
		if(this.myElement.getAttribute('menuOrientation') == 'horizontal') {
			this.horizontal = 1;
		} else {
			this.horizontal = 0;
		}
		
		// parent orientation
		if(this.parentMenu && this.parentMenu.horizontal) {
			this.parentHorizontal = 1;
		} else {
			this.parentHorizontal = 0;
		}
		
		// position adjustments
		this.childXAdjustment = 0;
		if(this.myElement.getAttribute('childXAdjustment')) {
			this.childXAdjustment = parseInt(this.myElement.getAttribute('childXAdjustment'));
			this._debug(this.myElement.id + " childXAdjustment [" + this.childXAdjustment + "]");
		}
		this.childYAdjustment = 0;
		if(this.myElement.getAttribute('childYAdjustment')) {
			this.childYAdjustment = parseInt(this.myElement.getAttribute('childYAdjustment'));
			this._debug(this.myElement.id + " childYAdjustment [" + this.childYAdjustment + "]");
		}
		
		this.xAdjustment = 0;
		if(this.myElement.getAttribute('xAdjustment')) {
			this.xAdjustment = parseInt(this.myElement.getAttribute('xAdjustment'));
		}
		this.yAdjustment = 0;
		if(this.myElement.getAttribute('yAdjustment')) {
			this.yAdjustment = parseInt(this.myElement.getAttribute('yAdjustment'));
		}
		
		if(this.myElement.getAttribute('mouseOverFontColor')) {
			this.mouseOverFontColor = this.myElement.getAttribute('mouseOverFontColor');
		}
		if(this.myElement.getAttribute('mouseOutFontColor')) {
			this.mouseOutFontColor = this.myElement.getAttribute('mouseOutFontColor');
		}
		// save the original font color
		this.originalFontColor = Element.getStyle(this.myElement, 'color');

		
		// get the children of this element
		this._find_children_by_type("DIV");
		
		// set up event handlers
		// only do this for menus with parents ie not for the root menu
		if(this.parentMenu) {
			//this.myElement.onclick = this._menuActivated.bindAsEventListener(this);
			this.myElement.onmouseover = this._menuActivated.bindAsEventListener(this);
			this.myElement.onmouseout = this._menuDeactivated.bindAsEventListener(this);
		} else {
			//this.showChildren();
		}
	},
	
	getHeight: function() {
		//return Element.getHeight(this.myElement);
		if(this.absoluteDimensions != null) {
			return this.absoluteDimensions.height;
		} else {
			var dimensions = Element.getDimensions(this.myElement);
			return dimensions.height;
		}
	},
	
	getWidth: function() {
		//return this.myElement.offsetWidth;
		if(this.absoluteDimensions != null) {
			return this.absoluteDimensions.width;
		} else {
			var dimensions = Element.getDimensions(this.myElement);
			return dimensions.width;
		}
	},
	
	show: function() {
		this.myElement.style.visibility = 'visible';
		this._show_instant();
	},
	
	hide: function() {
		this.hideChildren();
		this._hide_delayed();
		//this.myElement.style.visibility = 'visible';
	},
	
	hideChildren: function() {
		for(var childIndex in this.children) {
			var childMenu = this.children[childIndex];
			if(childMenu.hide) {
				childMenu.hide();
			}
		}
		
	},
	
	showChildren: function() {
		for(var childIndex in this.children) {
			var childMenu = this.children[childIndex];
			if(childMenu.show) {
				childMenu.show();
			}
		}
		
	},
	
	_find_children_by_type: function(type) {
		// loop over all the child nodes of the element
		// and add any children that match the node type
		// passed in
		for(var curChildIndex = 0; curChildIndex < this.myElement.childNodes.length; curChildIndex++) {
			var curChildElement = this.myElement.childNodes[curChildIndex];
			
			if((curChildElement == null) || (curChildElement.nodeName != type)) {
				continue;
			}
			this._add_child(curChildElement);
		}
	},

	_add_child: function(childElement) {
		if(!this.children) {
			this.children = new Array();
		}
		
		if(childElement.getAttribute('type') == 'container') {
			this.containerElement = childElement;
			// look for a X/Y offset
			this.containerXOffset = 0;
			this.containerYOffset = 0;
			if(childElement.getAttribute('xOffset')) {
				this.containerXOffset = parseInt(childElement.getAttribute('xOffset'));
			}
			if(childElement.getAttribute('yOffset')) {
				this.containerYOffset = parseInt(childElement.getAttribute('yOffset'));
			}
		} else {
			var curChildMenuEntry = new LookhereMenuEntry(this, childElement);
			
			if(!curChildMenuEntry._apply_style_to_children) {
				this._debug("menuEntry for childElement [" + childElement.id + "] not correct");
			} else {
				this.children.push(curChildMenuEntry);
			}
		}
	},

	_apply_style_to_children: function() {
		this._apply_style();
		
		if(this.children) {
			for(var childIndex = 0; childIndex < this.children.length; childIndex++) {
				var childMenu = this.children[childIndex];
				this._debug("childIndex [" + childIndex + "] childMenu [" + childMenu + "]");
				if(childMenu == null || !childMenu._apply_style_to_children) {
					debuggingElement.innerHTML += "childIndex [" + childIndex + "] is null!";
					continue;
				}
				childMenu._apply_style_to_children();
			}
		}
	},

	_apply_style: function() {
		// *** NOTE *** we set visibility to hidden, but show it so that 
		//				size calculations work correctly
		this.myElement.style.visibility = 'hidden';
		Element.show(this.myElement);

		this.myElement.style.position = 'absolute';
		this.myElement.style.zIndex = 2;

		if(this.containerElement) {
			this._debug("applying style to container element with id [" + this.containerElement.id + "] style.visible [" + this.containerElement.style.visible + "] style.display [" + this.containerElement.style.display + "]");
			//alert("_apply_style");
			this.containerElement.style.visibility = 'hidden';
			Element.show(this.containerElement);
			//this.containerElement.style.display = '';
			this.containerElement.style.position = 'absolute';
			this.containerElement.style.zIndex = 1;
		}
	},
	
	_align_children: function() {
		if(this.children) {
			var containerWidth = 0;
			var containerHeight = 0;
			
			for(var childIndex = 0; childIndex < this.children.length; childIndex++) {
				var childMenu = this.children[childIndex];
				childMenu._align_to_parent();
				childMenu._align_children();
				
				if(this.horizontal) {
					if(childMenu.getHeight() > containerHeight) {
						containerHeight = childMenu.getHeight();
					}
					containerWidth += childMenu.getWidth();
				} else {
					if(childMenu.getWidth() > containerWidth) {
						containerWidth = childMenu.getWidth();
					}
					containerHeight += childMenu.getHeight();
				}
			}
			if(this.containerElement) {
				this._debug("_align_children this.xAdjustment [" + this.xAdjustment + "] this.yAdjustment [" + this.yAdjustment + "] this.childXAdjustment [" + this.childXAdjustment + "] this.childYAdjustment + this.getHeight() [" + (this.childYAdjustment + this.getHeight()) + "]");
				//this._adjust_element_position(this.containerElement, this.childXAdjustment, this.childYAdjustment);
				var containerXAdjustment = this.childXAdjustment + this.containerXOffset;
				var containerYAdjustment = this.getHeight() + this.containerYOffset;
				this._adjust_element_position(this.containerElement, containerXAdjustment, containerYAdjustment);
				this._adjust_element_size(this.containerElement, containerWidth, containerHeight);
			}
		}

	},
	
	_align_to_parent: function() {
		this._debug("adjusting element [" + this.myElement.id + "] position x [" + this.xAdjustment + "] y [" + this.yAdjustment + "]");
		
		// align to parent element
		this._adjust_element_position(this.myElement, this.xAdjustment, this.yAdjustment);
		
	},
		
	_move_element: function(elementName, moveX, moveY) {
		var element = $(elementName);
		
		element.style.top = moveY + "px";
		element.style.left = moveX + "px";

		return false;
	},
	
	_adjust_element_size: function(elementName, width, height) {
		//alert("_adjust_element_size width [" + width + "] height [" + height + "]");
		var element = $(elementName);
		
		element.style.width = width + "px";
		element.style.height = height + "px";
	},

	_adjust_element_position: function(elementName, moveX, moveY) {
		var element = $(elementName);

		var curTop = parseInt(element.style.top);
		if(isNaN(curTop)) {
			curTop = 0;
		}
		curTop += moveY;

		var curLeft = parseInt(element.style.left);
		if(isNaN(curLeft)) {
			curLeft = 0;
		}
		curLeft += moveX;

		element.style.top = curTop + "px";
		element.style.left = curLeft + "px";
		
		return true;
	},

	_calculate_sizing: function() {
		// we have to get the dimensions when the position is ''
		var myElementCurPosition = this.myElement.style.position;
		this.myElement.style.position = '';
		this.absoluteDimensions = Element.getDimensions(this.myElement);
		this.myElement.style.position = myElementCurPosition;

		if(this.children) {
			for(var childIndex = 0; childIndex < this.children.length; childIndex++) {
				var childMenu = this.children[childIndex];
				childMenu._calculate_sizing();
			}
		}
	},
	
	_calculate_adjustments: function() {
		if(this.children) {
			this._debug("_calculate_adjustments [" + this.myElement.id + "] childXAdjustment [" + this.childXAdjustment + "] childYAdjustment [" + this.childYAdjustment + "]");

			for(var childIndex = 0; childIndex < this.children.length; childIndex++) {
				var childMenu = this.children[childIndex];
				this._debug("_calculate_adjustments [" + this.myElement.id + "] childMenu id [" + childMenu.myElement.id + "]");
				childMenu.xAdjustment += this.childXAdjustment;
				if(this.horizontal) {
					this.childXAdjustment += childMenu.getWidth();
					this._debug("_calculate_adjustments - horizontal [" + childMenu.xAdjustment + "] this.childXAdjustment [" + this.childXAdjustment + "] childMenu.getWidth() [" + childMenu.getWidth() + "]");
				} else {
					this._debug("_calculate_adjustments - vertical");
					childMenu.yAdjustment += this.childYAdjustment;
					this.childYAdjustment += childMenu.getHeight();
					
					if(!this.parentHorizontal) {
						this._debug("_calculate_adjustments - parentVertical");
						childMenu.xAdjustment += this.getWidth();
					} else {
						this._debug("_calculate_adjustments - parentHorizontal");
						childMenu.yAdjustment += this.getHeight();
					}
				}
				
				childMenu._calculate_adjustments();
			}
		}
	},
	
	_resize_children: function() {
		if(this.children) {
			this._debug("_resize_children [" + this.myElement.id + "] childXAdjustment [" + this.childXAdjustment + "] childYAdjustment [" + this.childYAdjustment + "]");

			for(var childIndex = 0; childIndex < this.children.length; childIndex++) {
				var childMenu = this.children[childIndex];
				
				//this.myElement.style.width = this.childXAdjustment;
				//this.myElement.style.height = this.childYAdjustment;
				
				childMenu._resize_children();
			}
		}
	},

	_menuActivated: function(event) {
		this._clear_interval();
		
		// first hide sibling children
		for(var siblingIndex in this.parentMenu.children) {
			var siblingMenu = this.parentMenu.children[siblingIndex];
			if(siblingMenu.hideChildren) {
				//siblingMenu.hideChildren();
				//siblingMenu.show();
				this._debug("siblingMenu show");
				siblingMenu._clear_interval();
			}
		}
		
		// change the current font color
		if(this.mouseOverFontColor != null) {
			this.myElement.style.color = this.mouseOverFontColor;
		}
		
		if(this.containerElement) {
			this._debug(this.myElement.id + "hideChildren id [" + this.myElement.id + "] - showing containerElement");
			this.containerElement.style.visibility = 'visible';
			Element.show(this.containerElement);
		} else {
			//this._debug(this.myElement.id + " -  hideChildren - no container");
		}

		
		if(this.children) {
			//this.myElement.className = this.activeCSSClassName;
			//alert("I was activated!");
			for(var childIndex in this.children) {
				var childMenu = this.children[childIndex];
				if(childMenu.show) {
					childMenu.show();
				} else {
					//alert("childMenu.show [" + childMenu.show + "]");
				}
			}
		}
		
		//event.stopPropagation();

		return true;
	},
	
	_menuDeactivated: function(event) {
		// first hide sibling children
		for(var siblingIndex in this.parentMenu.children) {
			var siblingMenu = this.parentMenu.children[siblingIndex];
			if(siblingMenu.hideChildren) {
				siblingMenu.hideChildren();
			}
		}
		
		// change the current font color
		// first save the old color
		if(this.mouseOutFontColor != null) {
			this.myElement.style.color = this.mouseOutFontColor;
		} else if(this.originalFontColor != null) {
			this.myElement.style.color = this.originalFontColor;
		} else {
			//this.myElement.style.backgroundColor = "#FFFFFF";
		}
		
		if(this.children) {
			//this.myElement.className = this.inactiveCSSClassName;
			//alert("I was activated!");
			for(var childIndex in this.children) {
				var childMenu = this.children[childIndex];
				if(childMenu.show) {
					childMenu.hide();
				} else {
					//alert("childMenu.show [" + childMenu.show + "]");
				}
			}
		}
		
		//event.stopPropagation();
		
		return true;
	},
	
	_hide_delayed: function() {
		this._clear_interval();
		
		// set up a new interval
		this.menuHideIntervalId = setInterval(this._hide_instant.bind(this), 20);
	},
	
	_hide_instant: function() {
		this._clear_interval();

		Element.hide(this.myElement);
		
		if(this.parentMenu.containerElement) {
			this._debug(this.myElement.id + "hideChildren id [" + this.myElement.id + "] - hiding containerElement");
			Element.hide(this.parentMenu.containerElement);
		}
	},
	
	_show_instant: function() {
		this._clear_interval();
		
		// show the menu
		this.myElement.style.visibility = 'visible';
		Element.show(this.myElement);
		//if(this.containerElement) {
		//	this._debug(this.myElement.id + "_show_instant id [" + this.myElement.id + "] - showing containerElement");
			//alert("showing containerElement");
		//	Element.show(this.containerElement);
		//}
	},
	
	_clear_interval: function() {
		// clear any hides that are waiting
		if(this.menuHideIntervalId) {
			clearInterval(this.menuHideIntervalId);
			this.menuHideIntervalId = null;
		}
	},

	_debug: function(debugString) {
		var debuggingElement = $('debuggingarea');
		
		if(debuggingElement) {
			debuggingElement.innerHTML += debugString + "<br>\n";
		}
	}
};

