/**
 * @author	Sven Kutzner
 * @copyright	2010 Sven Kutzner
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 */
function AdvancedPageMenu(menuId, activeMenuItem, style, direction, icons) {
	if(style != 'popup' && style != 'list') style = 'popup';
	if(direction != 'down' && direction != 'up') direction = 'down';

	this.activeMenuItem = activeMenuItem;
	this.icons = icons;
	this.style = style;
	this.direction = direction;
	this.menuId = menuId;
	this.menus = new Array();
	this.menuItems = new Array();
	
	/**
	 * Returns the offset of an element.
	 */
	this.getOffset = function(element) {
		var offsetLeft = element.offsetLeft;
		var offsetTop = element.offsetTop;
		
		while ((element = element.offsetParent) != null) {
			offsetLeft += element.offsetLeft;
			offsetTop += element.offsetTop;
		}
		
		return {'left' : offsetLeft, 'top' : offsetTop};
	}
	
	this.ucfirst = function(str) {
	    return str.substr(0,1).toUpperCase() + str.substr(1,str.length);
	}
	
	this.positionPopupMenu = function(id) {
		// check if there is a submenu for the current menu
		if(!this.menus[id]) return;
		var menuItem = this.menuItems[id];
		var target = document.getElementById('displayMenuItem-'+id);
		var offset = this.getOffset(target);
		var top = offset.top;
		var left = offset.left;
		
		// direction of the popup menu
		if(this.direction == 'up') {
			top -= this.menus[id].menu.offsetHeight;
			if(menuItem.parentId != 0) {
				left += target.offsetWidth;
				top += target.offsetHeight;
			}
		} else { // down is currently the default behaviour
			if(menuItem.parentId == 0) {
				top += target.offsetHeight;
			} else {
				left += target.offsetWidth;
			}
		}
		this.menus[id].menu.style.top = top+'px';
		this.menus[id].menu.style.left = left+'px';
	}
	
	this.nodeMouseOver = function(e, id) {
		this.positionPopupMenu(id);
		this.showMenu(id);
	}
	
	this.nodeMouseOut = function(e, id) {
		this.hideMenu(id);
	}

	this.menuMouseOver = function(e, id) {
		this.showMenu(id);
	}

	this.menuMouseOut = function(e, id) {
		this.hideMenu(id);
	}

	this.showMenu = function(id) {
		if(!this.menus[id]) return;
		
		var parentId = this.menuItems[id].parentId;
		this.menus[id].menu.style.visibility = '';
		if(parentId != 0) {
			this.showMenu(parentId);
		}
	}
	
	this.hideMenu = function(id) {
		if(!this.menus[id]) return;
		
		var parentId = this.menuItems[id].parentId;
		this.menus[id].menu.style.visibility = 'hidden';
		if(parentId != 0) {
			this.hideMenu(parentId);
		}
	}

	this.mouseOut = function(id) {
		this.hideMenu(menuId, id);
	}

	this.menuToggle = function(e, id) {
		// TODO: properly implement list style menu
	}
	
	this.openMenu = function(id) {
		// see menuToggle		
	}
	
	this.closeMenu = function(id) {
		// see menuToggle
	}
	
	this.createMenu = function(id) {
		var menu = document.createElement('div');
		var menuInner = document.createElement('div');
		var menuList = document.createElement('ul');
		menu.className = 'pageMenu advanced'+this.ucfirst(menuId);
		menu.style.zIndex = '50';
		menu.style.position = 'absolute';
		menu.style.visibility = 'hidden';
		menu.style.top = '-1000px';
		menu.style.left = '-1000px';
		menuInner.className = 'pageMenuInner';
		menu.appendChild(menuInner);
		menuInner.appendChild(menuList);
		document.body.appendChild(menu);
		Event.observe(menu, 'mouseover', this.menuMouseOver.bindAsEventListener(this, id));
		Event.observe(menu, 'mouseout', this.menuMouseOut.bindAsEventListener(this, id));
		var result = new Object();
		result['menu'] = menu;
		result['menuInner'] = menuInner;
		result['list'] = menuList;
		result['open'] = false;
		return result;
	}
	
	this.createMenuItem = function(id) {
		var menuItem = this.menuItems[id];
		// create list item
		var node = document.createElement('li');
		node.id = 'displayMenuItem-'+id;
		node.className = menuItem.node.className;

		// add anchor
		var link = document.createElement('a');
		link.href = menuItem.link;
		node.appendChild(link);
		
		// add icon
		if(menuItem.icon != null) {
			var icon = document.createElement('img');
			icon.src = menuItem.icon;
			link.appendChild(icon);
		}
		
		// add title
		var title = document.createElement('span');
		title.innerHTML = menuItem.title;
		link.appendChild(title);
		
		// bind events
		Event.observe(node, 'mouseover', this.nodeMouseOver.bindAsEventListener(this, id));
		Event.observe(node, 'mouseout', this.nodeMouseOut.bindAsEventListener(this, id));
		
		return node;
	}
	
	this.addMenu = function(parentId, node) {
		var id = node.id.replace(this.menuId+'Item-','');
		
		if(this.style == 'popup') {
			// return if this is a first level item
			if(parentId == 0) return;
			
			if(!this.menus[parentId]) {
				this.menus[parentId] = this.createMenu(parentId);
				var parentNode = document.getElementById('displayMenuItem-'+parentId);
				if(!parentNode.className.include('withChildren')) {
					parentNode.className += ' withChildren';
					// update the icon
					if(this.menuItems[parentId].parentId != 0) parentNode.getElementsByTagName('span')[0].style.backgroundImage = 'url("'+this.icons.arrow+'")';
				}
			}
			if(node) {
				var newNode = this.createMenuItem(id);
				this.menus[parentId].list.appendChild(newNode);
			}
		} else if(this.style == 'list') {
			var actionButton = document.createElement('img');
			actionButton.src = this.icons.plus;
			this.menuItems[id]['button'] = actionButton;
			Event.observe(actionButton, 'click', this.menuToggle.bindAsEventListener(this, id));
			node.insertBefore(actionButton, document.getElementById(this.menuId+'Link-'+id));
		}
	}
	
	this.addMenuItem = function(parentId, node) {
		var id = node.id.replace(this.menuId+'Item-','');
		var icon = document.getElementById(this.menuId+'Icon-'+id);
		var title = document.getElementById(this.menuId+'Title-'+id);
		var link = document.getElementById(this.menuId+'Link-'+id);
		this.menuItems[id] = new Object();
		this.menuItems[id]['id'] = id;
		this.menuItems[id]['parentId'] = parentId;
		this.menuItems[id]['icon'] = (icon != null) ? icon.src : null;
		this.menuItems[id]['title'] = (title != null) ? title.innerHTML : "";
		this.menuItems[id]['link'] = (link != null) ? link.href : "";
		this.menuItems[id]['node'] = node;
		 
		if(parentId == 0 && this.style == 'popup') {
			// specifiy new node id
			node.id = 'displayMenuItem-'+id;
			// add events
			Event.observe(node, 'mouseover', this.nodeMouseOver.bindAsEventListener(this, id));
			Event.observe(node, 'mouseout', this.nodeMouseOut.bindAsEventListener(this, id));
		} else {
			this.addMenu(parentId, node);
		}
		this.parseMenuItems(id);
	}
	
	this.parseMenuItems = function(itemId) {
		var root = document.getElementById(this.menuId+'Items-'+itemId);
		if(root != null) {
			var childCount = root.childNodes.length;
			var childNode = null;
			for(var i=0; i < childCount; i++) {
				childNode = root.childNodes[i];
				if(childNode.nodeName == 'LI') {
					this.addMenuItem(itemId, childNode);
				}
			}
		}
	}
	
	this.init = function() {
		this.parseMenuItems(0);
		if(this.stlye == 'list') this.openMenu(this.activeMenuItem);
	}
}
