var PrThemeBlueStreamMenu;

//== Constructor ==//

PrThemeBlueStreamMenu = function (root) {
	this.root = root;
	this.menuId = PrThemeBlueStreamMenu.menus.length;
	
	this.currentSection = null;
	this.transitionFrom = null;
	this.transitionStage = 0;
	this.transitionTimeout = null;
};

//== Prototype members ==//

PrThemeBlueStreamMenu.prototype = {
	initialize: function () {
		var detector, i, j, links, linkNode, node, nodes, subMenu;
		
		// Loop through the menu section elements.
		
		nodes = this.root.childNodes;
		
		for (i=0; i < nodes.length; ++i) {
			node = nodes[i];
			
			if (node.nodeType === 1) { // Element node
				subMenu = node.getElementsByTagName('ul')[0];
				
				node.prThemeBlueStream = {
					subMenu: subMenu,
					menu: this,
					i: i
				};
				
				subMenu.prThemeBlueStream = {
					initHeight: null,
					numItems: subMenu.getElementsByTagName('li').length
				};
				
				links = node.getElementsByTagName('a');
				
				PrThemeBlueStreamMenu.addEvent(links[0], 'click', PrThemeBlueStreamMenu.eventSectionClick);
				PrThemeBlueStreamMenu.addEvent(links[0], 'mousedown', PrThemeBlueStreamMenu.eventSectionMouseDown);
				
				for (j=links.length - 1; j >= 0; --j) {
					linkNode = links[j];
					
					linkNode.prThemeBlueStream = {
						li: node
					};
					
					PrThemeBlueStreamMenu.addEvent(linkNode, 'blur', PrThemeBlueStreamMenu.eventLiBlur);
					PrThemeBlueStreamMenu.addEvent(linkNode, 'focus', PrThemeBlueStreamMenu.eventLiFocus);
				}
				
				if (this.currentSection === null && PrThemeBlueStreamMenu.hasClassName(node, 'current')) {
					this.currentSection = node;
					PrThemeBlueStreamMenu.removeClassName(node, 'current');
					PrThemeBlueStreamMenu.addClassName(node, 'active');
				}
				else {
					PrThemeBlueStreamMenu.addClassName(node, 'inactive');
				}
				
				if (subMenu.offsetHeight !== undefined) {
					subMenu.prThemeBlueStream.initHeight = subMenu.offsetHeight;
				}
				
				if (node === this.currentSection) {
					subMenu.style.height = subMenu.prThemeBlueStream.initHeight+'px';
				}
				else {
					subMenu.style.height = '0px';
				}
			}
		}
		
		// Create font resize detector.
		
		detector = document.createElement('div');
		detector.style.height = 'auto';
		detector.style.margin = '0';
		detector.style.overflow = 'hidden';
		detector.style.padding = '0';
		detector.style.position = 'absolute';
		detector.style.top = '0';
		detector.style.width = '0';
		detector.style.visibility = 'hidden';
		detector.appendChild(document.createTextNode("\xa0"));
		document.body.appendChild(detector);
		
		PrThemeBlueStreamMenu.fontResizeDetector = detector;
		
		if (detector.offsetHeight !== undefined) {
			PrThemeBlueStreamMenu.initFontSize = detector.offsetHeight;
			PrThemeBlueStreamMenu.fontSize = detector.offsetHeight;
			
			window.setTimeout(PrThemeBlueStreamMenu.FontResizeDetectorTick, 20);
		}
		else {
			// The offsetHeight property isn't available. Don't detect changes.
			
			PrThemeBlueStreamMenu.initFontSize = 1;
			PrThemeBlueStreamMenu.fontSize = 1;
		}
	},
	
	selectSection: function (newSection) {
		if (newSection === this.currentSection) {
			return;
		}
		
		if (this.transitionStage !== 0) {
			if (this.transitionFrom !== null) {
				this.transitionFrom.prThemeBlueStream.subMenu.style.height = '0px';
				PrThemeBlueStreamMenu.removeClassName(this.transitionFrom, 'active');
				PrThemeBlueStreamMenu.removeClassName(this.transitionFrom, 'transition');
				PrThemeBlueStreamMenu.addClassName(this.transitionFrom, 'inactive');
			}
			
			if (this.transitionTimeout !== null) {
				window.clearTimeout(this.transitionTimeout);
				this.transitionTimeout = null;
			}
		}
		
		if (this.currentSection !== null) {
			PrThemeBlueStreamMenu.removeClassName(this.currentSection, 'active');
			PrThemeBlueStreamMenu.removeClassName(this.currentSection, 'clicked');
			PrThemeBlueStreamMenu.addClassName(this.currentSection, 'inactive');
			PrThemeBlueStreamMenu.addClassName(this.currentSection, 'transition');
		}
		
		PrThemeBlueStreamMenu.removeClassName(newSection, 'inactive');
		PrThemeBlueStreamMenu.addClassName(newSection, 'active');
		PrThemeBlueStreamMenu.addClassName(newSection, 'transition');
		
		this.transitionFrom = this.currentSection;
		this.transitionStage = 11;
		this.currentSection = newSection;
		
		this.transitionTimeout = window.setTimeout('PrThemeBlueStreamMenu.transitionTick('+this.menuId+')', 0);
	}
}

//== Static members ==//

// Properties.

PrThemeBlueStreamMenu.menus = [];
PrThemeBlueStreamMenu.menuSources = [];
PrThemeBlueStreamMenu.focusLinks = [];
PrThemeBlueStreamMenu.whitespaceRegExp = new RegExp('[ \n\r\t]+');
PrThemeBlueStreamMenu.fontResizeDetector = null;
PrThemeBlueStreamMenu.initFontSize = null;
PrThemeBlueStreamMenu.fontSize = null;

// Event model abstraction.

PrThemeBlueStreamMenu.addEvent = function (node, event, handler) {
	if (node.addEventListener) {
		node.addEventListener(event, handler, false);
	}
	else if (node.attachEvent) {
		node.attachEvent('on'+event, handler);
	}
	else {
		return false;
	}
	
	return true;
};

// Class manipulation.

PrThemeBlueStreamMenu.addClassName = function (node, className) {
	var newClassName;
	
	newClassName = node.className.split(PrThemeBlueStreamMenu.whitespaceRegExp);
	
	if (PrThemeBlueStreamMenu.arrayIndexOf(newClassName, className) === -1) {
		newClassName.push(className);
	}
	
	node.className = newClassName.join(' ');
};

PrThemeBlueStreamMenu.hasClassName = function (node, className) {
	return (PrThemeBlueStreamMenu.arrayIndexOf(node.className.split(PrThemeBlueStreamMenu.whitespaceRegExp), className) !== -1);
};

PrThemeBlueStreamMenu.removeClassName = function (node, className) {
	var index, newClassName
	
	newClassName = node.className.split(PrThemeBlueStreamMenu.whitespaceRegExp);
	
	index = PrThemeBlueStreamMenu.arrayIndexOf(newClassName, className);
	
	if (index !== -1) {
		delete newClassName[index];
	}
	
	node.className = newClassName.join(' ');
};

// Other functions.

PrThemeBlueStreamMenu.arrayIndexOf = function (array, value) {
	var i, len;
	
	len = array.length;
	
	for (i=0; i < len; ++i) {
		if (array[i] === value) {
			return i;
		}
	}
	
	return -1;
};

PrThemeBlueStreamMenu.autodiscoverMenus = function (rootId, classNamePattern) {
	PrThemeBlueStreamMenu.menuSources.push({rootId: rootId, classNamePattern: classNamePattern});
};

PrThemeBlueStreamMenu.eventLiBlur = function (e) {
	var node;
	
	node = PrThemeBlueStreamMenu.getEventSource(this, e);
	
	if (node === false) {
		return;
	}
	
	node = node.prThemeBlueStream.li;
	
	PrThemeBlueStreamMenu.removeClassName(node, 'clicked');
};

PrThemeBlueStreamMenu.eventLiFocus = function (e) {
	var node;
	
	node = PrThemeBlueStreamMenu.getEventSource(this, e);
	
	if (node === false) {
		return;
	}
	
	PrThemeBlueStreamMenu.focusLinks.push(node);
	PrThemeBlueStreamMenu.addClassName(node, 'init-transition');
	window.setTimeout(PrThemeBlueStreamMenu.restoreFocusLinks, 0);
	
	node = node.prThemeBlueStream.li;
	
	node.prThemeBlueStream.menu.selectSection(node);
};

PrThemeBlueStreamMenu.eventSectionMouseDown = function (e) {
	var node;
	
	node = PrThemeBlueStreamMenu.getEventSource(this, e);
	
	if (node === false) {
		return;
	}
	
	node = node.prThemeBlueStream.li;
	
	node.prThemeBlueStream.menu.selectSection(node);
	
	PrThemeBlueStreamMenu.addClassName(node, 'clicked');
};

PrThemeBlueStreamMenu.eventSectionClick = function (e) {
	if (e.preventDefault !== undefined) {
		e.preventDefault();
	}
	
	return false;
};

PrThemeBlueStreamMenu.getEventSource = function (context, e) {
	if (context.prThemeBlueStream !== undefined) {
		return context;
	}
	
	if (e.srcElement !== undefined && e.srcElement.prThemeBlueStream !== undefined) {
		return e.srcElement;
	}
	
	return false;
};

PrThemeBlueStreamMenu.prepareMenuSources = function () {
	var i, j, menuSource, node, nodes, regExp, root;
	
	for (i=0; i < this.menuSources.length; ++i) {
		menuSource = this.menuSources[i];
		
		root = document.getElementById(menuSource.rootId);
		
		regExp = new RegExp('(?:^|\s)'+menuSource.classNamePattern+'(?:\s|$)');
		
		nodes = root.getElementsByTagName('ul');
		
		for (j=0; j < nodes.length; ++j) {
			node = nodes[j];
			
			if (node.className.match(regExp)) {
				PrThemeBlueStreamMenu.menus.push(new PrThemeBlueStreamMenu(node));
			}
		}
	}
};

PrThemeBlueStreamMenu.restoreFocusLinks = function () {
	var i;
	
	for (i = PrThemeBlueStreamMenu.focusLinks.length - 1; i >= 0; --i) {
		PrThemeBlueStreamMenu.removeClassName(PrThemeBlueStreamMenu.focusLinks[i], 'init-transition');
	}
	
	PrThemeBlueStreamMenu.focusLinks = [];
};

PrThemeBlueStreamMenu.transitionTick = function (menuId) {
	var menu, subMenu;
	
	menu = PrThemeBlueStreamMenu.menus[menuId];
	
	--menu.transitionStage;
	
	if (menu.transitionFrom !== null) {
		// Previous section
		subMenu = menu.transitionFrom.prThemeBlueStream.subMenu;
		subMenu.style.height = ((subMenu.prThemeBlueStream.initHeight + subMenu.prThemeBlueStream.numItems * (PrThemeBlueStreamMenu.fontSize - PrThemeBlueStreamMenu.initFontSize)) * menu.transitionStage / 10)+'px';
	}
	
	// Newly selected section
	subMenu = menu.currentSection.prThemeBlueStream.subMenu;
	subMenu.style.height = ((subMenu.prThemeBlueStream.initHeight + subMenu.prThemeBlueStream.numItems * (PrThemeBlueStreamMenu.fontSize - PrThemeBlueStreamMenu.initFontSize)) * (10 - menu.transitionStage) / 10)+'px';
	
	if (menu.transitionStage > 0) {
		menu.transitionTimeout = window.setTimeout('PrThemeBlueStreamMenu.transitionTick('+menuId+')', 20);
	}
	else {
		if (menu.transitionFrom !== null) {
			PrThemeBlueStreamMenu.removeClassName(menu.transitionFrom, 'transition');
		}
		
		PrThemeBlueStreamMenu.removeClassName(menu.currentSection, 'transition');
		menu.transitionTimeout = null;
	}
};

PrThemeBlueStreamMenu.FontResizeDetectorTick = function () {
	var fontSize, i, menu, subMenu;
	
	fontSize = PrThemeBlueStreamMenu.fontResizeDetector.offsetHeight;
	
	if (fontSize !== PrThemeBlueStreamMenu.fontSize) {
		// The font size has changed.
		
		PrThemeBlueStreamMenu.fontSize = fontSize;
		
		for (i=0; i < PrThemeBlueStreamMenu.menus.length; ++i) {
			menu = PrThemeBlueStreamMenu.menus[i];
			subMenu = menu.currentSection.prThemeBlueStream.subMenu;
			
			subMenu.style.height = ((subMenu.prThemeBlueStream.initHeight + subMenu.prThemeBlueStream.numItems * (fontSize - PrThemeBlueStreamMenu.initFontSize)) * (10 - menu.transitionStage) / 10)+'px';
		}
	}
	
	window.setTimeout(PrThemeBlueStreamMenu.FontResizeDetectorTick, 20);
};

//== Set up menus ==//

PrThemeBlueStreamMenu.addEvent(window, 'load', function () {
	var i, menu;
	
	PrThemeBlueStreamMenu.prepareMenuSources();
	
	for (i=0; i < PrThemeBlueStreamMenu.menus.length; ++i) {
		menu = PrThemeBlueStreamMenu.menus[i];
		
		menu.initialize();
	}
});

