//  constant regular expressions
var flowbarsPattern = new RegExp("(^|\\s)flowbar(\\s|$)");
var flowsPattern = new RegExp("(^|\\s)flow(\\s|$)");

var fixedPattern = new RegExp("(^|\\s)fixed(\\s|$)");
var overlayPattern = new RegExp("(^|\\s)overlay(\\s|$)");
var thumbnailPattern = new RegExp("(^|\\s)thumbnail(\\s|$)");
var imagePattern = new RegExp("(^|\\s)image(\\s|$)");
var hiddenPattern = new RegExp("(^|\\s)hidden(\\s|$)");
var leftPattern = new RegExp("(^|\\s)left(\\s|$)");
var centrePattern = new RegExp("(^|\\s)centre(\\s|$)");
var rightPattern = new RegExp("(^|\\s)right(\\s|$)");

//  the size of the current document
var pagewidth, pageheight;
var currentpage;
var flowbartop = 87;

//  the currently selected flowbar element, and the flows inside it
var baseflowbar;
var selectedflowbar;
var selectedflowbarname;
var flows;
var targetpositions;

//  transient: timeout until the animation hits again
var timeout;
var animates = false;
var timeout2;


function splashinit (defaultpage) {
	ensureDocumentDimensions();
	
	if (pageheight) {
		var adjustheight = Math.round((pageheight / 2) - 160);
		var superheader = document.getElementById("superheader");
		if (superheader) {
			superheader.style.height = adjustheight + "px";
		}
	}
	
	init(defaultpage);
}


function init (defaultpage) {
	ensureDocumentDimensions();
	
	//  set up the flowbars
	currentpage = defaultpage;
	flowbarcontainer = document.getElementById("flowbarcontainer3");
	flowbartop = getAbsoluteTop(flowbarcontainer);
	selectflowbar(currentpage, true);
	
	//  adjust the sub-table to cover space under the main table
	if (pageheight) {
		var adjustheight = Math.round(pageheight - 200);
		var subtable = document.getElementById("sub");
		if (subtable) {
			subtable.style.height = adjustheight + "px";
		}
	}
}

function ensureDocumentDimensions() {
	if (!pagewidth) {
		if (self.innerWidth) {
			pagewidth = self.innerWidth;
		} else if (document.documentElement && document.documentElement.clientWidth) {
			pagewidth = document.documentElement.clientWidth;
		} else if (document.body) {
			pagewidth = document.body.clientWidth;
		}
	}
	if (!pageheight) {
		if (self.innerHeight) {
			pageheight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) {
			pageheight = document.documentElement.clientHeight;
		} else if (document.body) {
			pageheight = document.body.clientHeight;
		}
	}
}

function hover(pagename) {
	if (timeout2 != null) {
		clearTimeout(timeout2);
		timeout2 = null;
	}
	
	selectflowbar(pagename, true);
}

function unhover(pagename) {
	if (timeout2 != null) {
		clearTimeout(timeout2);
		timeout2 = null;
	}
	timeout2 = setTimeout("unhover2('"+pagename+"');", 1000);
	
	//if (selectedflowbarname == pagename) {
	//	selectflowbar(currentpage, false);
	//}
}

function unhover2(pagename) {
	if (timeout2 != null) {
		clearTimeout(timeout2);
		timeout2 = null;
	}
	if (selectedflowbarname == pagename) {
		selectflowbar(currentpage, false);
	}
}


/*
 *   Make the given flowbar visible and set its animation going. Hide other flowbars
 */

function selectflowbar(flowbarname, nudging) {
	//  if that flowbar is already selected, don't bother changing
	if (selectedflowbar && selectedflowbarname == flowbarname) {
		return;
	}
	
	//  finish off any animation still going
	if (selectedflowbar) {
		var endfunction = window[selectedflowbar.id + "_end"];
		if (endfunction) {
			endfunction();
		}
		selectedflowbar.style.visibility = "hidden";
		selectedflowbar = null;
		flows = null;
		targetpositions = null;
	}

	//  find the correct flowbar to launch
	selectedflowbarname = flowbarname;
	selectedflowbar = document.getElementById(flowbarname);
	if (selectedflowbar == null) {
		selectedflowbarname = null;
		if (nudging) { nudge(); }
		return;
	}
	
	//  stop animation now
	if (timeout != null) {
		clearTimeout(timeout);
		timeout = null;
	}
	
	//  stop and hide all the other flows
	var divs = document.getElementsByTagName("div");
	for (var h = 0; h < divs.length; h++) {
		var div = divs[h];
		if (flowbarsPattern.test(div.className) && div != selectedflowbar) {
			if (!hiddenPattern.test(div.className)) {
				div.className = div.className + " hidden";
			}
		}
	}
	if (hiddenPattern.test(selectedflowbar.className)) {
		selectedflowbar.className = selectedflowbar.className.replace(/hidden/, " ");
	}

	//  collect the flowing elements
	divs = selectedflowbar.getElementsByTagName("div");
	flows = Array();
	for (var h = 0; h < divs.length; h++) {
		var div = divs[h];
		if (flowsPattern.test(div.className)) {
			flows.push(div);
		}
	}
	targetpositions = new Array(flows.length);
	
	//  show the selected flowbar
	selectedflowbar.style.position = "absolute";
	selectedflowbar.style.visibility = "visible";
	selectedflowbar.style.top = flowbartop + "px";
	selectedflowbar.style.left = "6px";
	if (pagewidth) {
		selectedflowbar.style.width = (pagewidth - 12) + "px";
	}
	
	//  show the flows, and set them at random inital places
	for (var i=0; i<flows.length; i++) {
		var flow = flows[i];
		flow.style.visibility = "visible";
		flow.style.position = "absolute";
		flow.style.top = "0px";
	}
	
	//  set the animation going
	if (nudging) {
		nudge();
	}
}


/*
 *   Set the animation going again by choosing new random locations for each of the flows.
 */

function nudge () {
	if (flows == null) {
		return;
	}
	
	if (timeout != null) {
		clearTimeout(timeout);
		timeout = null;
	}
	
	timeout = setTimeout("nudge2()", 0);
}

function nudge2() {
	//  make sure the animation isn't running multiple times
	if (timeout != null) {
		clearTimeout(timeout);
		timeout = null;
	}
	if (flows == null) {
		return;
	}
	
	for (var i=0; i<flows.length; i++) {
		var flow = flows[i];
		if (overlayPattern.test(flow.className)) {
			targetpositions[i] = 250;
		} else if (thumbnailPattern.test(flow.className)) {
			targetpositions[i] = 0;
		} else if (leftPattern.test(flow.className)) {
			targetpositions[i] = 0;
		} else if (centrePattern.test(flow.className)) {
			targetpositions[i] = (pagewidth - flow.offsetWidth) / 2;
		} else if (rightPattern.test(flow.className)) {
			targetpositions[i] = pagewidth - flow.offsetWidth - 12;
		} else {
			if (imagePattern.test(flow.className)) {
				targetpositions[i] = randomPosition(flow.offsetWidth, 300);
			} else {
				targetpositions[i] = randomPosition(flow.offsetWidth, 0);
			}
		}
		
		if (fixedPattern.test(flow.className)) {
			flow.style.left = targetpositions[i] + "px";
		}
	}
	
	if (selectedflowbar != null) {
		var nudgefunction = window[selectedflowbar.id + "_nudge"];
		if (nudgefunction) {
			nudgefunction();
		}
	}
	
	//  progress
	animates = true;
	if (timeout != null) {
		clearTimeout(timeout);
		timeout = null;
	}
	timeout = setTimeout("step(0)", 20);
}


/*
 *  One step in the animation
 */

function step (number) {
	//  make sure the animation isn't running multiple times
	if (timeout != null) {
		clearTimeout(timeout);
		timeout = null;
	}
	if (flows == null) {
		return;
	}
	
	// move them
	var stillrunning = false;
	for (var i=0; i<flows.length; i++) {
		var flow = flows[i];
		var position = Number(flow.offsetLeft);
		if (position != targetpositions[i]) {
			if (position < targetpositions[i]) {
				speed = ((targetpositions[i] - position) / 6) + 1;
				position += speed;
				if (position > targetpositions[i]) {
					position = targetpositions[i];
				}
			} else {
				speed = ((position - targetpositions[i]) / 6) + 1;
				position -= speed;
				if (position < targetpositions[i]) {
					position = targetpositions[i];
				}
			}
			if (flow.style && flow.style.left) {
				flow.style.left = position + "px";
			}
			stillrunning = true;
		}
	}
	
	//  do flow-specific animation
	if (selectedflowbar) {
		var stepfunction = window[selectedflowbar.id + "_step"];
		if (stepfunction) {
			if (stepfunction()) {
				stillrunning = true;
			}
		}
	}
	
	//  progress
	animates = true;
	if (stillrunning) {
		if (timeout != null) {
			clearTimeout(timeout);
			timeout = null;
		}
		timeout = setTimeout("step(" + (number + 1) + ")", 20);
	} else {
		//  finish the animation
		if (selectedflowbar) {
			var endfunction = window[selectedflowbar.id + "_end"];
			if (endfunction) {
				endfunction();
			}
		}
	}
}


/*
 *  Select a random left value for the element that will stop it going off either side of the page,
 *  taking the object's width into account and allowing a 6px border each side.
 */

function randomPosition (objectWidth, minLeft) {
	var min = Number(minLeft);
	if (min < 0)
		min = 0;
	var max = pagewidth - objectWidth - 12;
	var position = Math.round(Math.random() * (pagewidth - objectWidth + 100)) - 50;
	if (position > max) {
		position = max;
	}
	if (position < min) {
		position = min;
	}
	return position;
}


/*
 *  Overcome browser inconsistencies and give the absolute top value of the given object.
 *  Use this to ensure that an object floated absolutely will match up with its parent's location.
 */

function getAbsoluteTop (object) {
	var top = object.offsetTop;
	if (object.offsetParent) {
		top += getAbsoluteTop(object.offsetParent);
	}
	return top;
}