var w=null;function log(m){if(!w)w=window.open();w.document.write(m+'<br />');}

Page = function () {
	this.navigation = new Navigation("navigation");
	if (document.getElementById("Carousel")) {
		var candidates = document.getElementsByTagName("div");
		for (var i=0; i < candidates.length; i++) {
			if (candidates[i].className.indexOf("main") != -1) {
				var delay = (candidates[i].className.indexOf("carousel-last") != -1) ? 6000 : 2000;
				new Rotator(candidates[i].getElementsByTagName("div")[0], candidates[i].getElementsByTagName("ul")[0], "li", candidates[i].getElementsByTagName("h2")[0], 3, 180, delay);
			}
			
		}
	}	
	var page = this;
	window.onunload = function () {page.destruct()}
}
Page.prototype.destruct = function () {
	//Memory management
}
Object.prototype.method = function (method) {
	var context = this;
	return function () {
		method.apply(context, arguments);
		if (this.blur && this.tagName=="A") this.blur();
		return false;
	}
}
function isChild (ancestor, candidate) {
	while (candidate && candidate != ancestor.parentNode) {
		if (candidate == ancestor) return true;
		try {
			candidate = candidate.parentNode;
		} catch (c) {return false}
	}
	return false;
}
Navigation = function (nodeID) {
	var navigation = this;

	this.rootNode = document.getElementById(nodeID);
	this.state = this.CLOSED;

	// Add behavior
	this.rootNode.onmouseout = function (e) {
		var destination = (e) ? e.relatedTarget : window.event.toElement;
		navigation.changeState(navigation.LOSTMOUSE, destination, this.menuitem);
	}
	var menuopener = function (e) {
		var destination = (e) ? e.relatedTarget : window.event.toElement;
		navigation.changeState(navigation.GOTMOUSE, destination, this.menuitem);
	}
	var as = this.rootNode.getElementsByTagName("a");
	for (var i=0; i < as.length; i++) {// Only treat 1st level links that have submenu's
		if (as[i].parentNode.parentNode.parentNode == this.rootNode && as[i].parentNode.getElementsByTagName("a").length > 1) {
			as[i].onmouseover = menuopener;

			as[i].menuitem = new Object();
			as[i].menuitem.submenu = as[i].parentNode.getElementsByTagName("ul")[0];
			as[i].menuitem.height =  this.calculateMenuHeight(as[i].menuitem.submenu);
			this.hide(as[i].menuitem.submenu);
		}
	}
	this.animator = null;// Will contain dynamically created Animator objects
}

//Event types
Navigation.prototype.GOTMOUSE  = 0;
Navigation.prototype.LOSTMOUSE = 1;

//States
Navigation.prototype.OPEN      = 0;
Navigation.prototype.CLOSED    = 1;
Navigation.prototype.ANIMATING = 2;
Navigation.prototype.HOT       = 3;

Navigation.prototype.changeState = function (eventType, destination, newItem) {

	if (this.isChild(destination) && !newItem) {
		return;//Ignore event bubbling when open, top item events got newItems, so they fall through
	}
	switch (eventType) {
		case this.GOTMOUSE:
			switch (this.state) {
				case this.HOT:
					this.activeItem = newItem;
				break;
				case this.CLOSED:// Menu will open in half a second unless the fuse is put out
					this.fuse = setTimeout(this.method(this.open), 300);
					this.activeItem = newItem;
					this.state = this.HOT;
				break;
				case this.OPEN:// Switch between main categories
					if (newItem != this.activeItem) {
						this.adjust(newItem);
					}
				break;
				case this.ANIMATING:// Stop and animate to new target
					if (newItem != this.activeItem) {
						this.animator.stop();
						this.adjust(newItem);
					}
				break;
			}
		break;
		case this.LOSTMOUSE:
			switch (this.state) {
				case (this.HOT):// Lost the mouse, cancel menu opening
					clearTimeout(this.fuse);
					this.activeItem = null;
					this.state = this.CLOSED;
				break;
				case (this.OPEN):// Close it
					this.close();
				break;
				case this.ANIMATING:// Stop and animate to closed position
					this.animator.stop();
					this.close();
				break;
			}
		break;
	}
}
Navigation.prototype.open = function () {
	this.state = this.ANIMATING;
	this.show(this.activeItem.submenu);
	this.animator = new Animator(this.rootNode.offsetHeight, this.activeItem.height, this.method(this.setHeight), this.method(this.opened));
	this.animator.start();
}
Navigation.prototype.opened = function () {
	this.state = this.OPEN;
	this.animator = null;
}

Navigation.prototype.close = function () {
	this.state = this.ANIMATING;
	this.animator = new Animator(this.rootNode.offsetHeight, 24, this.method(this.setHeight), this.method(this.closed));
	this.animator.start();
}
Navigation.prototype.closed = function () {
	this.state = this.CLOSED;
	this.hide(this.activeItem.submenu);
	this.activeItem = null;
	this.animator = null;
}
Navigation.prototype.adjust = function (newItem) {
	this.state = this.ANIMATING;
	this.hide(this.activeItem.submenu);
	this.show(newItem.submenu);
	this.activeItem = newItem;
	this.animator = new Animator(this.rootNode.offsetHeight, this.activeItem.height, this.method(this.setHeight), this.method(this.opened));
	this.animator.start();
}

Navigation.prototype.setHeight = function (x) {
	this.rootNode.style.height = x+"px";
}
Navigation.prototype.hide = function (object) {
	if (document.all) {object.style.visibility = "hidden"} else {object.style.display = "none";}
}
Navigation.prototype.show = function (object) {
	if (document.all) {object.style.visibility = "visible"} else {object.style.display = "block";}
}
Navigation.prototype.isChild = function (candidate) {
	while (candidate && candidate != this.rootNode.parentNode) {
		if (candidate == this.rootNode) return true;
		try {
			candidate = candidate.parentNode;
		} catch (c) {return false}
	}
	return false;
}
Navigation.prototype.calculateMenuHeight = function (list) {
	var total = 0;

	if (list.getElementsByTagName("div").length > 0) {
		var cols = list.getElementsByTagName("div");
		for (var i=0; i < cols.length; i++) total = Math.max(cols[i].offsetHeight, total);
	} else {
		var items = list.getElementsByTagName("a");
		for (var i=0; i < items.length; i++) {
			if (items[i].parentNode.parentNode == list)
				total += 25;
			else
				total += 19;
		}
	}
	return total+30;
}
Animator = function (startValue, endValue, f, t, r) {
	this.step  = 10;			//The step by which timer counts from 0 to 100
	this.rate  = 10;			//The rate in ms at which steps are taken
	this.power = 2;				//The steepness of the animation curve
	this.type  = this.NONE;	//The type of easing

	this.min = startValue;
	this.max = endValue;
	this.isReversing = false;
	this.animateFunction = f;
	this.terminateFunction = t;
	this.reversalFunction = r;

	this.precalc = new Array(100);
	for (var i=0; i <= 100; i++) this.precalc[i] = this.calculate(i);
}
Animator.prototype.NONE      = 0;
Animator.prototype.EASEIN    = 1;
Animator.prototype.EASEOUT   = 2;
Animator.prototype.EASEINOUT = 3;

Animator.prototype.setStep = function (step) {
	this.step = step;
}
Animator.prototype.setRate = function (rate) {
	this.rate = rate;
}
Animator.prototype.setPower = function (power) {
	this.power = power;
	for (var i=0; i <= 100; i++) this.precalc[i] = this.calculate(i);
}
Animator.prototype.setType = function (type) {
	this.type = type;
	for (var i=0; i <= 100; i++) this.precalc[i] = this.calculate(i);
}
Animator.prototype.setAnimateFunction = function (f) {
	this.animateFunction = f;
}
Animator.prototype.start = function () {
	if (this.interval) return;
	this.time = 0;
	this.isReversing = false;
	this.interval = setInterval(this.method(this.animate), this.rate);
}
Animator.prototype.reverse = function () {
	this.isReversing = (this.isReversing) ? false : true;
}
Animator.prototype.stop = function () {
	if (this.interval) clearInterval(this.interval);
	this.interval = null;
}
Animator.prototype.pause = function () {
	//this.paused = true;
	if (this.interval) clearInterval(this.interval);
}
Animator.prototype.resume = function () {
	//this.paused = false;
	this.interval = setInterval(this.method(this.animate), this.rate);
}
Animator.prototype.isAnimating = function () {
	return Boolean(this.interval);
}
Animator.prototype.animate = function () {
	if (this.time >= 0 && this.time <= 100) {
		this.animateFunction(this.precalc[this.time]);
		this.time = (this.isReversing) ? this.time - this.step : this.time + this.step;
	} else {
		clearInterval(this.interval);
		this.interval = null;
		if (!this.isReversing && this.terminateFunction) this.terminateFunction();
		if (this.isReversing && this.reversalFunction) this.reversalFunction();
	}
}
Animator.prototype.calculate = function (t) {
	t = t/100;
	var factor;
	switch (this.type) {
		case this.NONE      : factor = this.easeNone(t);break;
		case this.EASEIN    : factor = this.easeIn(t);break;
		case this.EASEOUT   : factor = this.easeOut(t);break;
		case this.EASEINOUT : factor = this.easeInOut(t);break;
	}
	return parseInt(this.min + factor*(this.max-this.min));
}
Animator.prototype.easeNone = function (t) {
	return t;
}
Animator.prototype.easeIn = function (t) {
	return Math.pow(t,this.power);
}
Animator.prototype.easeOut = function (t) {
	return 1-this.easeIn(1-t);
}
Animator.prototype.easeInOut = function (t) {
	if (t < 0.5) return this.easeIn(t*2)/2;
	return 0.5+this.easeOut((t-0.5)*2)/2;
}


Rotator = function (scrollableElement, itemContainer, itemTagName, buttonContainer, visibleItems, scrollDistance, initialDelay) {
	this.itemSize = scrollDistance;
	this.visibleItems = visibleItems;
	this.orientation = 0;

	this.scrollable = scrollableElement;
	this.items = itemContainer.getElementsByTagName(itemTagName);
	this.totalItems = this.items.length;
	if (this.totalItems <= this.visibleItems) return;

	var rotator = this;//Needed for closures below

	var leftBut = document.createElement("a");
	leftBut.className = "leftBut";
	leftBut.href = "#";
	leftBut.onclick = function () {this.blur();rotator.manual();rotator.back();return false}
	buttonContainer.appendChild(leftBut);

	var rightBut = document.createElement("a");
	rightBut.className = "rightBut";
	rightBut.href = "#";
	rightBut.onclick = function () {this.blur();rotator.manual();rotator.forward();return false}
	buttonContainer.appendChild(rightBut);

	var bottomClones = new Array(this.visibleItems);
	var topClones = new Array(this.visibleItems);
	/* Duplicate head and tail of the item list */
	for (var i = 0; i < this.visibleItems; i++) {
		bottomClones[i] = this.items[this.totalItems - 1 - i].cloneNode(true);
		topClones[i] = this.items[i].cloneNode(true);
	}
	/* Grow the list */
	for (var i = 0; i < this.visibleItems; i++) {
		itemContainer.insertBefore(bottomClones[i], this.items[0]);//items is dynamic, so items[0] always refers to first item
		itemContainer.appendChild(topClones[i]);
	}

	this.index = this.visibleItems;
	if (this.orientation) this.scrollable.scrollTop = this.index*this.itemSize; else this.scrollable.scrollLeft = this.index*this.itemSize;

	this.scrollForward = new Animator(0, this.itemSize, this.method(this.animateForward), this.method(this.checkIndex));
	this.scrollForward.setStep(3);
	this.scrollForward.setType(this.scrollForward.EASEINOUT);
	this.scrollForward.setRate(20);
	this.scrollBack = new Animator(0, this.itemSize, this.method(this.animateBack), this.method(this.checkIndex));
	this.scrollBack.setStep(3);
	this.scrollBack.setType(this.scrollForward.EASEINOUT);
	this.scrollBack.setRate(20);

	itemContainer.controller = this;
	itemContainer.onmouseover = function (){this.controller.pause()};
	itemContainer.onmouseout = function (){if (!isChild(itemContainer,this) || this == itemContainer) this.controller.resume()};

	this.auto = setTimeout(this.method(this.automatic), initialDelay);
}

Rotator.prototype.setHorizontalMode = function () {this.orientation = 0}
Rotator.prototype.setVerticalMode = function () {this.orientation = 1}

Rotator.prototype.automatic = function () {
	if (this.isPaused) {
		this.restart = setTimeout(this.method(this.automatic), 5000);
		return;
	}
	this.forward();
	if (this.restart) clearInterval(this.restart);
	this.restart = null;
	this.auto = setInterval(this.method(this.forward), 6000);
}
Rotator.prototype.manual = function () {
	if (!this.auto || this.isPaused) return;
	if (this.animating) {
		this.scrollForward.stop();
		this.checkIndex();
		this.animating = false;
	}
	if (this.auto) clearInterval(this.auto);
	this.auto = null;
	if (this.restart) clearInterval(this.restart);
	this.restart = setTimeout(this.method(this.automatic), 5000);
}
Rotator.prototype.forward = function () {
	if (this.animating) return;
	this.animating = this.scrollForward;
	this.index++;
	this.scrollForward.start();
}
Rotator.prototype.animateForward = function (value) {
	if (this.orientation) this.scrollable.scrollTop = (this.index-1)*this.itemSize + value;
	else this.scrollable.scrollLeft = (this.index-1)*this.itemSize + value;
}
Rotator.prototype.back = function () {
	if (this.animating) return;
	this.animating = this.scrollBack;
	this.index--;
	this.scrollBack.start();
}
Rotator.prototype.animateBack = function (value) {
	if (this.orientation) this.scrollable.scrollTop = (this.index+1)*this.itemSize - value;
	else this.scrollable.scrollLeft = (this.index+1)*this.itemSize - value;
}
Rotator.prototype.checkIndex = function () {
	if (this.index == 0) this.index = this.totalItems;
	if (this.index == this.totalItems + this.visibleItems) this.index = this.visibleItems;
	if (this.orientation) this.scrollable.scrollTop = this.index*this.itemSize; else this.scrollable.scrollLeft = this.index*this.itemSize;
	this.animating = false;
}
Rotator.prototype.pause = function () {
	if (this.animating) {
		this.animating.pause();
	} else {
		this.manual();
	}
	this.isPaused = true;
}
Rotator.prototype.resume = function () {
	if (this.animating) {
		this.animating.resume();
	}
	this.isPaused = false;
}
