function Menus(data, options) {
	var menusById = new Object();
	var menusByType = new Array();
	var crumb = new Array();
	var settings = $.extend(wcm, options);
	
	initIds(data);
	initMenus(data);
	initCrumb();
	
	function initIds(menus) {
		var selected = false;
		for (var i=0; menus && i<menus.length; i++) {
			var menu = menus[i];
			menu.isSelected = isSelected;
			menu.getLink = getLink;
			menu.getHref = getHref;
			menu.getStyle = getStyle;
			menu.getDepth = getDepth;
			menu.getDelimeter = getDelimeter;
			menu.getOnClick = getOnClick;
			menu.isVisible = isVisible;
			
			menusById[menu.id] = menu;
			initIds(menu.sub);
		}
		return selected;
	}
	
	function initMenus(menus) {
		var visible = new Array();
		for (var i=0; menus && i<menus.length; i++) {
			var menu = menus[i];
			if (menu.isVisible()) {
				visible.push(menu);
				if (!menu.parent) {
					getMenus(menu.type).push(menu);
				}
				menu.sub = initMenus(menu.sub);
			}
		}
		return visible;
	}
	
	function initCrumb() {
		var menu = getRootMenu(menusById[settings.menu]);
		if (menu) {
			menu.selected = true;
		}		
		while (menu) {
			crumb.push(menu);
			menu = menusById[menu.parent];
		}
		crumb.reverse();
	}
	
	this.getApplication = function() {
		return getMenus('A');
	}
	
	this.getGlobal = function() {
		return getMenus('G');
	}

	this.getTop = function() {
		return getMenus('N');
	}

	this.getCrumb = function() {
		return crumb;
	}

	this.getFooter = function() {
		return getMenus('F');
	}

	this.getMenu = function(id) {
		return menusById[id];
	}
	
	function getQueryString() {
		return document.location.search || '';
	}
	
	function getMenus(type) {
		if (!menusByType[type]) {
			menusByType[type] = new Array();
		}
		return menusByType[type];
	}

	function getRootMenu(menu) {
		var link = menusById[menu.link];
		return !link || link == menu ? menu : getRootMenu(link);
	}

	function isVisible() {
		var menu = this;
		var dav = getRootMenu(this).dav;
		return (!settings.live || menu.active == 'Y') && (!dav || dav.length == 0 || containsAny(dav, settings.user.security));
	}
	
	function isSelected() {
		return contains(crumb, this);
	}
	
	function getLink() {
		var pageInfo = document.pageInfo;
		var menu = this;
		var type = menu.url;
		if (type == '/cda/header/loginLogout') {
			if (settings.login) {
				return '<a name="m' + menu.id + '" href="/cda/login' + getQueryString() + '">' + settings.login + '</a>';
			} else if (settings.logout) {
				return '<a name="m' + menu.id + '" href="/cda/logout' + getQueryString() + '">' + settings.logout + '</a>';
			}
		} else if (type == '/cda/header/toggleSecurity') {
			menu.url = 'javascript:return toggleSecurity();';
		} else if (type == '/cda/header/toggleEditor') {
			menu.url = 'javascript:return toggleEditor();';
		} else if (type == '/cda/header/contactUs') {
			menu.url = '/cda/contactUs' + getQueryString(); 
		} else if (type == '/cda/footer/printerFriendly') {
			var friendly = new $.query(document.location).get('printerFriendly');
			return '<a name="m' + menu.id + '"></a>' + (friendly ? '' : '<a href="#" id="printerFriendly" onclick="window.open(new $.query(document.location).set(\'printerFriendly\', \'true\')); return false;">' + menu.name + '</a>');
		} else if (type == '/cda/footer/confidentialityCode') {
			return !pageInfo || !pageInfo.confidentiality ? '' : '<a name="m' + menu.id + '"></a>' + menu.name + ': <b><a id="confidentiality" href="/cda/layout/generalText?commonText=footer-confidentiality">' + pageInfo.confidentiality + '</a></b>';
		} else if (type == '/cda/footer/webmaster') {
			return !pageInfo || !pageInfo.webmaster ? '' : '<a name="m' + menu.id + '"></a>' + menu.name + ':&nbsp;<a id="webmaster" href="mailto:' + pageInfo.webmaster.email + '">' + pageInfo.webmaster.name + '</a>';
		} else if (type == '/cda/footer/contentOwner') {
			return !pageInfo || !pageInfo.owner ? '' : '<a name="m' + menu.id + '"></a>' + menu.name + ':&nbsp;<a id="owner" href="mailto:' + pageInfo.owner.email + '">' + pageInfo.owner.name + '</a>';
		} else if (type == '/cda/footer/author') {
			return !pageInfo || !pageInfo.author ? '' : '<a name="m' + menu.id + '"></a>' + menu.name + ':&nbsp;<a id="author" href="mailto:' + pageInfo.author.email + '">' + pageInfo.author.name + '</a>';
		} else if (type == '/cda/footer/currentDate') {
			return !pageInfo || !pageInfo.currentDate ? '' : '<a name="m' + menu.id + '"></a>' + (pageInfo.currentDate || '').replace('CURRENT_DATE', getCurrentDate());
		}
		return '<a name="m' + menu.id + '" href="' + menu.getHref() + '"' + menu.getOnClick() + '>' + menu.name + '</a>';
	}

	function getHref() {
		var menu = this;
		if (menu.alias) return menu.alias;// + (settings.language ? '?x=' + settings.language : '');
		if (menu.url) {
			if (menu.urlType == 'N' || menu.urlType == 'I') return menu.url;
		}
		return '/cda/layout?m=' + getRootMenu(menu).id + (settings.language ? '&x=' + settings.language : '');
	}
	
	function getOnClick() {
		var menu = this;
		if (menu.urlType == 'N') {
			return ' onclick="openWindow(\'' + menu.getHref().escapeJavaScript() + '\', \'learnMore\'); return false;"';
		} else if (menu.url && menu.url.startsWith('javascript:')) {
			return ' onclick="' + menu.url.substringAfter('javascript:') + '"';
		}
		return '';
	}
	
	function getStyle() {
		var menu = this;
		var parent = menu.sub && menu.sub.length > 0;
		var selected = menu.selected;
		var expanded = menu.isSelected();
		
		return (parent ? 'p' : 'nP') + '-' + (selected ? 's' : (expanded ? 'e' : (parent ? 'nE' : 'nS')));
	}
	
	function getDepth() {
		var parent = menusById[this.parent];
		return parent ? parent.getDepth() + 1 : 0;
	}
	
	function getDelimeter() {
		var depth = this.getDepth();
		if (depth == 2) return '<em class=sys>&raquo;&nbsp;</em>';
		if (depth == 3) return '<em class=sys>&#8250;&nbsp;</em>';
		if (depth == 4) return '<em class=sys>&middot;&nbsp;</em>';
		return '';
	}
}

var menus;
function getMenus() {
	if (!menus) {
		menus = lookupMenus();
	}
	return menus;
}

function lookupMenus(options) {
	var m;
	$.ajax({
		type: "GET",
		url: '/cda/lookup/menus',
		data: { params : toJSON({ domain : 'menu', site : wcm.site, language : wcm.language }), x : wcm.language },
		dataType: "json",
		cache: true,
		async: false,
		success: function(data) {
			m = new Menus(data, options);
		}
	});
	return m;
}

function initApplication(cont) {
	if (typeof createApplication == 'function') {
		var menus = getMenus().getApplication();
		if (menus && menus.length > 0) {
			$(cont).append(createApplication(menus));
		} else {
			$(cont).hide();
		}
	}
}

function initGlobalNav(cont) {
	if (typeof createGlobalNav == 'function') {
		$(cont).html(createGlobalNav(getMenus().getGlobal()));
	}
}

function initTopNav(cont) {
	if (typeof createTopNav == 'function') {
		$(cont).html(createTopNav(getMenus().getTop()));
	}
}

function initLeftNav(cont) {
	if (typeof createLeftNav == 'function') {
		$(cont).html(createLeftNav(getMenus().getCrumb()));
	}
}

function initFooter(cont) {
	if (typeof createFooter == 'function') {
		$(cont).html(createFooter(getMenus().getFooter()));
	}
}

function initCrumb(cont) {
	if (typeof createCrumb == 'function') {
		$(cont).html(createCrumb(getMenus().getCrumb()));
	}
}

function initSiteMap(cont) {
	if (typeof createSiteMap == 'function') {
		var menus = $(createSiteMap(getMenus().getTop()), 'div');
		var $cont = $(cont);
		var start = 0;
		var max = Math.ceil(menus.length / $cont.length);
		$cont.each(function() {
			$(this).html(menus.slice(start, start + max));
			start += max;
		});
	}
}