function Carousel(opt){
	this.options = opt
	this.backOverMethod = new MethodCall(this, this.backOver).dispatch;
	this.forwardOverMethod = new MethodCall(this, this.forwardOver).dispatch;
	this.backOutMethod = new MethodCall(this, this.backOut).dispatch;
	this.forwardOutMethod = new MethodCall(this, this.forwardOut).dispatch;
	this.onTick = new MethodCall(this, this.tick).dispatch
	this.sync = new Sync();
	this.sync.interval = 20;
	this.motion = 5;
}
Carousel.prototype.forwardOver = function (){
	this.motion = -1 * Math.abs(this.motion);
	this.sync.addListener(this.onTick);
	this.sync.start();
}
Carousel.prototype.forwardOut = function (){
	this.sync.removeListener(this.onTick);
}
Carousel.prototype.backOver = function (){
	this.motion = Math.abs(this.motion);
	this.sync.addListener(this.onTick);
	this.sync.start();
}
Carousel.prototype.backOut = function (){
	this.sync.removeListener(this.onTick);
}
Carousel.prototype.tick = function (elapsed){
	var motion = this.motion * elapsed;
	var left = parseFloat(getCurrentStyle(this.ul, "left", ""))
	if(isNaN(left))
		left = 0;
	left += motion;

	if(left > 0) 
		left -= this.totalWidth;
	else if(left < -this.totalWidth)
		left += this.totalWidth;
	this.ul.style.left = left + "px";
}
Carousel.prototype.load = function (){
	var ul = getElement(this.options.id);
	var div = document.createElement("DIV");
	ul.parentNode.insertBefore(div, ul);
	div.appendChild(ul);
	div.id = ul.id + "_container";
	var lis = ul.getElementsByTagName("LI");
	this.totalWidth = 0;
	var len = lis.length;
	for(var i=0; i<len; i++){
		this.styleList(lis[i]);
		ul.appendChild(lis[i].cloneNode(true));
	}
	ul.style.margin = 0;
	ul.style.padding = 0;
	ul.style.cssFloat = "left";
	ul.style.styleFloat = "left";
	if(getCurrentStyle(ul, "position") != "absolute")
		ul.style.position = "relative";

	for(i=0; i<len; i++){
		this.totalWidth += lis[i].offsetWidth;
	}
		
	ul.style.width = this.totalWidth * 2 + "px";
	this.ul = ul;
	div.style.width = (this.options.width || 200) + "px";
 	div.style.overflow = "hidden";

	var backDiv = document.createElement("DIV");
	backDiv.className = "back";
	backDiv.appendChild(document.createTextNode("back"));
	div.insertBefore(backDiv, ul);
	div.style.position = "relative"; //Needed for IE6's overflow bug

/*	
	var back = document.createElement("A");
	back.href="#";
	back.appendChild(document.createTextNode("back"));
	backDiv.appendChild(back);
*/
	registerEvent(backDiv, "mouseover", this.backOverMethod);
	registerEvent(backDiv, "mouseout", this.backOutMethod);
	
	var forwardDiv = document.createElement("DIV");
	forwardDiv.className = "forward";	
	forwardDiv.appendChild(document.createTextNode("forward"));
	div.appendChild(forwardDiv);
	/*
	var forward = document.createElement("A");
	forward.href="#";
	forward.appendChild(document.createTextNode("forward"));
	forwardDiv.appendChild(forward);
	*/
	registerEvent(forwardDiv, "mouseover", this.forwardOverMethod);
	registerEvent(forwardDiv, "mouseout", this.forwardOutMethod);
}
Carousel.prototype.styleList = function(li) {
	li.style.cssFloat = "left";
	li.style.styleFloat = "left";
	li.style.display = "block";
	li.style.listStyle = "none";
}



Carousel.init = function(opt){
	var c = new Carousel(opt);
	registerEvent(window, "load", new MethodCall(c, c.load).dispatch);
}


function Sync(){
	var time1;
	var time2;
	this.interval = 0;
	this.timer = 0;
	var callArray = new Array()
	var callCount = 0
	var latestCall = 0;
	var started = false;
	var self = this;
	
	this.start = function (iInterval){
		if(started)
			return;
		started = true;
		if(iInterval)
			this.interval = iInterval;
		time1 = new Date();
		latestCall = new Date();
		this.timer = setTimeout(callListeners, this.interval)
	}
	this.addListener = function (oFunction){
		if(!oFunction)
			return;
		callArray[callArray.length] = oFunction
	}
	this.removeListener = function (oFunction){
		var bFound = false;
		for (var i=0; i < callArray.length; i++) {
		    if(callArray[i] == oFunction){
				callArray[i] = callArray[callArray.length - 1]
				callArray.length--;
				bFound = true;
			}
		}
	}
	function callListeners(){
		var d = new Date();
		var milliseconds = d.getTime() - latestCall.getTime()
		latestCall = d;
		for (var i=0; i < callArray.length; i++) {
			callArray[i](milliseconds/self.interval);
		}
		
		if(i != 0){
			setTimeout(callListeners, self.interval);
		}else{
			time2 = new Date();
			//window.status = Math.ceil((time2.getTime() - time1.getTime()) / 100);
			if(self.onComplete)
				this.onComplete();
			started = false;
		}
	}
	return this;
}