
// ///// NAVIGATION BASE

var AbstractBrowser = function () {

	// ///// STATIC

	AbstractBrowser.AGENT_MZ = 1;
	AbstractBrowser.AGENT_OP = 2;
	AbstractBrowser.AGENT_IE = 3;
	AbstractBrowser.AGENT_SF = 4;
	AbstractBrowser.AGENT_UNKNOWN = 0;

	AbstractBrowser.CLASS_CSS2 = 1;
	AbstractBrowser.CLASS_UNKNOWN = 0;

	AbstractBrowser.SYSTEM_WIN = 1;
	AbstractBrowser.SYSTEM_MAC = 2;
	AbstractBrowser.SYSTEM_UNKNOWN = 0;

	// ///// MEMBERS

	this.agent = null;
	this.version = null;
	this.system = null;

	// ///// CONSTRUCTOR

	// get agent name
	if(document.layers || navigator.appVersion.match(/MSIE 4/gi)) {
		this.agent = AbstractBrowser.AGENT_UNKNOWN;
		this.version = 0;
	}
	else if(navigator.userAgent.match(/gecko/gi) || navigator.userAgent.match(/netscape/gi)) {
		this.agent = AbstractBrowser.AGENT_MZ;
		this.version = 7;
	}
	else if(navigator.userAgent.match(/safari/gi)) {
		this.agent = AbstractBrowser.AGENT_SF;
		this.version = 7;
	}
	else if(navigator.userAgent.match(/opera/gi) && navigator.userAgent.match(/7\./gi)) {
		if(parseInt(navigator.userAgent.charAt(navigator.userAgent.indexOf("/") + 1)) < 7) {
			this.agent = AbstractBrowser.AGENT_UNKNOWN;
			this.version = 0;
		}
		else {
			this.agent = AbstractBrowser.AGENT_OP;
			this.version = 7;
		}
	}
	else if(navigator.userAgent.match(/msie/gi)) {
		this.agent = AbstractBrowser.AGENT_IE;
		this.version = (navigator.appVersion.match(/MSIE 5/gi))? 5 : 6;
	}
	else {
		this.agent = AbstractBrowser.AGENT_UNKNOWN;
		this.version = 0;
	}

	// get system name
	if(navigator.platform.match(/win/gi)) {
		this.system = AbstractBrowser.SYSTEM_WIN;
	}
	else if(navigator.platform.match(/mac/gi)) {
		this.system = AbstractBrowser.SYSTEM_MAC;
	}
	else {
		this.system = AbstractBrowser.SYSTEM_UNKNOWN;
	}

	// ///// METHODS

	// getCurrentStyle
	this.getCurrentStyle = function(node, prop) {
		if(this.agent == AbstractBrowser.AGENT_MZ && this.system == AbstractBrowser.SYSTEM_WIN) {
			try {
				return window.getComputedStyle(node, null)[prop];
			}
			catch(e) { return null; }
		}
		if(this.agent == AbstractBrowser.AGENT_IE) {
			return node.currentStyle[prop];
		}
		return null;
	};
	// print
	this.print = function(win) {
		if(!win) win = window.top;
		if(this.agent == AbstractBrowser.AGENT_IE) win.document.execCommand("Print");
		else win.print();
	};
	// getNextNode
	this.getNextNode = function(node) {
		while(node.nextSibling) {
			node = node.nextSibling;
			if(node.nodeName != "#text") return node;
		}
	};
	// getPreviousNode
	this.getPreviousNode = function(node) {
		while(node.previousSibling) {
			node = node.previousSibling;
			if(node.nodeName != "#text") return node;
		}
	};
	// getNextNodeByTagName
	this.getNextNodeByTagName = function(node, tagname) {
		while(node.nextSibling) {
			node = node.nextSibling;
			if(node.nodeName.toUpperCase() == tagname.toUpperCase()) return node;
		}
	};
	// getEvent
	this.getEvent = function(args) { // args: arguments object of event-handler function
		if(this.agent == AbstractBrowser.AGENT_IE) {
			return (window.event)? window.event : null;
		}
		else {
			return (args && args[0] && args[0].eventPhase)? args[0] : null;
		}
	};
	// getEventSource
	this.getEventSource = function(e) {
		if(this.agent == AbstractBrowser.AGENT_IE) {
			return (e.srcElement)? e.srcElement : null;
		}
		else {
			var src = e.target; // event.target may be text node on early mozillas
			if(src && src.nodeName == "#text") src = src.parentNode;
			return (src)? src : null;
		}
	};
};

var browser = new AbstractBrowser();


// ////////////////////////////////////////////////////////////////////////////

var Navigation = function(id, treerootid, treewritedelegate, activeitemid) {

	// ///// MEMBERS

	this.id = id;
	this.isinit = false;
	this.browser = null;

	this.treerootid = treerootid;
	this.treeroot = null;
	this.treewritedelegate = (typeof treewritedelegate == "function")? treewritedelegate : null;
	this.views = new Object();

	this.activeitemid = activeitemid;
	this.activeitem = null;

	// ///// CONSTRUCTOR

	if(!window.browser || !this.id) {
		throw new Error("Navigation: (id:\"" + this.id + "\") missing critical args!");
	}
	this.browser = window.browser;

	// register nav in global navs array
	if(!Navigation.navs) Navigation.navs = new Object();
	Navigation.navs[this.id] = this;

	// register load handler for navigation start
	if(Navigation.isinit != true) {
		var loadhandler = function() {
			Navigation.initAll(true);
		};
		if(typeof window.addEventListener != 'undefined' || typeof document.addEventListener != 'undefined') {
			var base = (typeof window.addEventListener != 'undefined')? window : document;
			base.addEventListener('load', loadhandler, false);
		}
		else if(typeof window.attachEvent != 'undefined') {
			window.attachEvent('onload', loadhandler);
		}
		else if(browser.agent == AbstractBrowser.AGENT_IE && browser.system == AbstractBrowser.SYSTEM_MAC) {
			if(typeof window.onload == "function") {
				var oldhandler = window.onload;
				var newhandler = function() {
					oldhandler();
					loadhandler();
				};
				window.onload = newhandler;
			}
			else {
				window.onload = loadhandler;
			}
		}
		Navigation.isinit = true;
	}

	// ///// METHODS

	this.init = function(mustdraw) {
		if(this.isinit == false) {
			// link treeroot
			if(this.treerootid) {
				// if treerootid is an array, the first element will be the id of the treeroot (this will be used also for url matching)
				if(this.treerootid.constructor.toString().toLowerCase().indexOf("array") > -1) {
					var treeroot = document.getElementById(this.treerootid[0]);
				}
				else {
					var treeroot = document.getElementById(this.treerootid);
				}
				if(treeroot) {
					this.treeroot = treeroot;
				}
			}
			// write nav tree
			this.write();
			// get active nav item
			this.activeitem = this.getActiveItem();
			// init nav views
			for(var viewid in this.views) {
				this.views[viewid].init();
			}
			// draw navigation
			if(mustdraw) {
				this.draw();
			}
		}
	};
	this.getViewById = function(id) {
		for(var viewid in this.views) {
			if(viewid == id) return this.views[viewid];
		}
		return null;
	};
	this.addView = function(viewid, view) {
		view.nav = this;
		view.id = viewid;
		this.views[viewid] = view;

		if(view.addcssurl && view.addcssurl != "") {
			document.write('<link type="text/css" rel="stylesheet" href="' + view.addcssurl + '">\n');
		}
	};
	this.draw = function() {
		for(var viewid in this.views) {
			this.views[viewid].draw();
		}
	};
	this.write = function() {
		if(this.treeroot && this.treewritedelegate && typeof this.treewritedelegate == "function") {
			this.treewritedelegate(this.treeroot);
		}
	};

	this.getActiveItem = function() { // url matching heuristics
		var directoryIndexes = new Array("index.html", "index.jsp", "default.asp");
		var node = null;
		// if activeitemid is an array, the first element will be the id of the activeitem
		if(this.activeitemid && this.activeitemid.constructor.toString().toLowerCase().indexOf("array") > -1) {
			var aid = this.activeitemid[0];
		}
		else var aid = this.activeitemid;
		// loads this.activeitemid if it is just the NAME of the variable with the real id
		if(window[aid]) aid = window[aid];
		if(aid) {
			if(!node) node = document.getElementById(aid);
		}
		// try to map it based on the page url
		if(!node && this.treeroot) {
			var node = null;
			var rexpHost = new RegExp(document.location.protocol + "//" + document.location.host);
			var docPath = document.location.href.replace(rexpHost, "");
			docPath = docPath.replace(/\#.*/, "");
			docPath = docPath.replace(/\?.*/, "");

			var navlinks = this.treeroot.getElementsByTagName("a");
			for(var i = 0; i < navlinks.length; i++) {
				if(browser.agent == AbstractBrowser.AGENT_IE || browser.agent == AbstractBrowser.AGENT_OP) {
					var rexpEmptyHref = new RegExp(/(\#)/);
					rexpEmptyHref.exec("#"); // reset RegExp object
					var rexpHref = new RegExp(/<[aA][^>]+href=["]{0,1}([^"|^\s]+)/);
					rexpHref.exec(navlinks[i].outerHTML);
					var lnkPathBIS = navlinks[i].outerHTML.match(/<[aA][^>]+href=["]{0,1}([^"|^\s]+)/gi);
					var lnkPath = RegExp.$1;
					if(lnkPath.charAt(lnkPath.length - 1) == "#" || lnkPath.charAt(lnkPath.length - 1) == "?") {
						lnkPath = lnkPath.replace(new RegExp(document.location.href), "");
					}
					lnkPath = lnkPath.replace(rexpHost, "");
				}
				else {
					lnkPath = navlinks[i].getAttribute("href").replace(rexpHost, "");
				}
				if(lnkPath != "#") {
					lnkPath = lnkPath.replace(/\#.*/, "");
					lnkPath = lnkPath.replace(/\?.*/, "");
					if(docPath == lnkPath) {
						return navlinks[i].parentNode;
					}
					if(lnkPath.indexOf(docPath) == 0 && lnkPath.lastIndexOf("/") == docPath.lastIndexOf("/")) {
						for(var j = 0; j < directoryIndexes.length; j++) {
							var al = (lnkPath.lastIndexOf("/") == lnkPath.length - 1)? lnkPath + directoryIndexes[j] : lnkPath;
							var dl = (docPath.lastIndexOf("/") == docPath.length - 1)? docPath + directoryIndexes[j] : docPath;
							if(al == dl) {
								return navlinks[i].parentNode;
							}
						}
					}
				}
			}
		}
		return node;
	};

	return this;
};
Navigation.initAll = function(mustdraw) {
	if(Navigation.navs) {
		for(var navid in Navigation.navs) {
			Navigation.navs[navid].init(mustdraw);
		}
	}
	if(Page.adjustLayout && typeof Page.adjustLayout == "function") Page.adjustLayout();
};
Navigation.getById = function(id) {
	for(var navid in Navigation.navs) {
		if(navid == id) return Navigation.navs[navid];
	}
	return null;
};

// ////////////////////////////////////////////////////////////////////////////

var NavigationView = function(viewportid, delegates, constants, addcssurl) {

	// ///// MEMBERS

	this.id = null;
	this.nav = null;
	this.isinit = false;

	this.viewportid = viewportid;
	this.viewport = null;

	this.delegates = new Array();
	this.addcssurl = addcssurl;
	this.constants = constants;

	// ///// METHODS

	this.init = function() {
		if(this.viewportid) {
			var viewport = document.getElementById(this.viewportid);
			if(viewport) {
				this.viewport = viewport;
				this.isinit = true;
			}
		}
	};
	this.delegates = delegates;
	this.draw = function() {
		if(this.isinit) {
			if(this.delegates["draw"]) this.delegates["draw"](this);
		}
	};
};


// ////////////////////////////////////////////////////////////////////////////


// ///// MAIN NAVIGATION

// delegates

var funcs_tab = new Array();
funcs_tab["draw"] = function(viewref) {
	var consts = viewref.constants;
	var navid = viewref.nav.id;
	var viewid = viewref.id;

	// check for double lines
	var brs = viewref.viewport.getElementsByTagName("br");
	for(var i = 0; i < brs.length; i++) {
		var items = brs[i].parentNode.parentNode.parentNode.getElementsByTagName("a");
		for(var j = 0; j < items.length; j++) {
			if(items[j].getElementsByTagName("br").length == 0) {
				items[j].innerHTML = items[j].innerHTML + "<br/>&nbsp;";
			}
		}
	}
	// set active item
	if(viewref.nav.activeitem) {
		var node = viewref.nav.activeitem;
		while(node != viewref.viewport) {
			node.className = consts.LAYOUT_CLASSNAME_CURRENT;
			node = node.parentNode.parentNode;
		}
	}
};

// constants

var consts_tab = new Array();
consts_tab["LAYOUT_CLASSNAME_CURRENT"] = "current";


// ///// CONTENT NAVIGATION

// delegates

var funcs_lefthand = new Array();
funcs_lefthand["draw"] = function(viewref) {
	// get Click on hole Nav
	viewref.viewport.onclick = function() {
		var src = browser.getEventSource(browser.getEvent(arguments));
		var name = src.nodeName.toLowerCase();
		if(name == "li") {
			var link = src.getElementsByTagName("a")[0];
			if(link.onclick) {
				link.onclick();
			}
			else {
				window.location.href = link;
			}
		}
	};
	// setup nav
	var items = viewref.viewport.getElementsByTagName("a");
	for(var i = 0; i < items.length; i++) {
		items[i].navview = viewref;
		if(items[i].parentNode.className.indexOf("title") != -1) {
			items[i].onclick = viewref.delegates["title_CLICK"];
			items[i].setAttribute("href", "javascript:void(0);");
		}
	}
	// pre open
	var activenode = viewref.nav.activeitem;
	if(activenode) {
		activenode.className += "Active";
		while(activenode.parentNode.className != "level3") {
			activenode = activenode.parentNode;
			activenode.className += "Active";
		}
	}
};
funcs_lefthand["title_CLICK"] = function() {
	var collapseAll = function(navview) {
		var items = navview.viewport.getElementsByTagName("li");
		for(var i = 0; i < items.length; i++) {
			if(items[i].className.indexOf("Active") != -1 && items[i].id != navview.nav.activeitemid) {
				items[i].className = items[i].className.substr(0, items[i].className.length - 6);
			}
		}
		var items = navview.viewport.getElementsByTagName("ul");
		for(var i = 0; i < items.length; i++){
			if(items[i].className.indexOf("Active") != -1) {
				items[i].className = items[i].className.substr(0, items[i].className.length - 6);
			}
		}
	};
	var item = this.parentNode;
	if(item.className.indexOf("Active") != -1) {
		if (item.id.length > 3) {
			item.childNodes[2].className = item.childNodes[2].className.substr(0, item.childNodes[2].className.length - 6);
			item.className = item.className.substr(0, item.className.length-6)
		}
		else {
			collapseAll(this.navview);
		}
	}
	else {
		collapseAll(this.navview);
		item.childNodes[2].className += "Active";
		item.className += "Active";
		while(item.parentNode.className != "level3") {
			item = item.parentNode;
			item.className += "Active";
		}
	}
	if(Page.adjustLayout && typeof Page.adjustLayout == "function") Page.adjustLayout();
};


// ///// PAGE TRAIL NAVIGATION

// delegates

var funcs_pagetrail = new Array();
funcs_pagetrail["draw"] = function(viewref) {
	var activeitemids = viewref.nav.activeitemid;
	var sections = new Array();

	for(var i = 0; i < viewref.nav.activeitemid.length; i++) {
		var section = new Array();
		var treeroot = document.getElementById(viewref.nav.treerootid[i]);
		if(i == 0) { // if main treeroot (first id in treerootid's array) nav has tried url automatch
			var item = viewref.nav.activeitem;
		}
		else {
			var itemid = (window[activeitemids[i]])? window[activeitemids[i]] : activeitemids[i];
			var item = document.getElementById(itemid);
		}
		if(item) {
			if(treeroot.id == "tabNavRoot") {
				if(item.parentNode.parentNode == treeroot) { // first tab only
					var link = item.getElementsByTagName("a")[0];
					section[section.length] = link.cloneNode(true);
				}
				else {
					var link = item.getElementsByTagName("a")[0];
					section[section.length] = link.cloneNode(true);
					item = item.parentNode.parentNode;
					while(item != treeroot) {
						var link = item.getElementsByTagName("ul")[0].getElementsByTagName("a")[0];
						var nlink = link.cloneNode(true);
						nlink.innerHTML = item.getElementsByTagName("a")[0].innerHTML;
						section[section.length] = nlink;
						item = item.parentNode.parentNode;
					}
				}
			}
			if(treeroot.id == "lefthandNavRoot") {
				while(item != treeroot) {
					if(item == viewref.nav.activeitem) {
						var link = item.getElementsByTagName("a")[0];
						var nlink = link.cloneNode(true);
					}
					else {
						var link = item.getElementsByTagName("ul")[0].getElementsByTagName("a")[0];
						var nlink = link.cloneNode(true);
						nlink.innerHTML = item.getElementsByTagName("a")[0].innerHTML;
					}
					section[section.length] = nlink;
					item = item.parentNode.parentNode;
				}
			}
		}
		sections[sections.length] = section;
	}
	// build sequence
	var navitems = new Array();
	sections.reverse();
	for(var i = 0; i < sections.length; i++) {
		sections[i].reverse();
		navitems = navitems.concat(sections[i]);
	};
	// remove last element ...
	navitems = navitems.slice(0, -1);
	// generate trail
	for(var i = 0; i < navitems.length; i++) {
		viewref.viewport.appendChild(navitems[i]);
		if(i < navitems.length - 1) {
			viewref.viewport.appendChild(document.createTextNode(" / "));
		}
	}
};


// ///// RUNTIME

tabnav = new Navigation("tabnav", "tabNavRoot", null, "L1_ID");
tabnav.addView("tabmenu", new NavigationView("tabNavRoot", funcs_tab, consts_tab, null));

lefthandnav = new Navigation("lefthandnav", "lefthandNavRoot", null, "L3_ID");
lefthandnav.addView("lefthandmenu", new NavigationView("lefthandNavRoot", funcs_lefthand, null, null));

trailnav = new Navigation("trailnav", ["lefthandNavRoot", "tabNavRoot"], null, ["L3_ID", "L1_ID"]);
trailnav.addView("pagetrail", new NavigationView("trailNavRoot", funcs_pagetrail, null, null));