Rotator = function(config) {
	var _self = this;
	this.wrapEl = null;
	this.items = new Array();
	this.switchOnMouseOver = false;
	this.duration = 8000;
	
	this.currentItem = 0;
	this.pause = false;
	this.timer = null;
	this.fadeTimer = null;
	
	if (!config || !config.id || !config.items) {
		alert('missing params');
		return;
	}

	this.wrapEl = document.getElementById(config.id);
	if (config.duration !== null) {
		this.duration = config.duration;
	}
	
	if (config.switchOnMouseOver !== null) {
		this.switchOnMouseOver = config.switchOnMouseOver;
	}

	// add all items
	for (i = 0; i < config.items.length; i++) {
		this.items[i] = new Array();
		
		this.items[i].el = document.createElement('li');
		this.items[i].el.setAttribute('id', config.items[i].id);
		this.items[i].el.className = 'rotator_item';
		
		if (config.items[i].content) {
			this.items[i].el.innerHTML = config.items[i].content;
		} else {
			this.items[i].el.innerHTML = document.getElementById(config.items[i].id).innerHTML;
		}
		
		
		if (config.items[i].thumbnail) {
			this.items[i].thumbnailEl = document.createElement('li');
			this.items[i].thumbnailEl.innerHTML = config.items[i].thumbnail;
			
			this.items[i].thumbnailEl.i = i;
			this.items[i].thumbnailEl.setAttribute('id', config.items[i].id + '_thumb');

			if (_self.switchOnMouseOver) {
				this.items[i].thumbnailEl.onmouseover = function() {_self.switchTo(this.i);};
			} else {
				this.items[i].thumbnailEl.onclick = function() {_self.switchTo(this.i);};
			}
		}
		
		if (i == this.currentItem) {
			this.items[i].el.style.opacity = 1;
			this.items[i].el.style.display = "block";
			this.items[i].el.style.filter = 'alpha(opacity = 100)';
			if (this.items[i].thumbnailEl) {
				this.items[i].thumbnailEl.className = 'rotator_item_thumb active';
			}
		} else {
			this.items[i].el.style.opacity = 0;
			this.items[i].el.style.display = "none";
			this.items[i].el.style.filter = 'alpha(opacity = 0)';
			if (this.items[i].thumbnailEl) {
				this.items[i].thumbnailEl.className = 'rotator_item_thumb inactive';
			}
		}
	}
	
	this.wrapEl.innerHTML = '<ul class="rotator_items"></ul><ul class="rotator_item_thumbs"></ul>';
	
	for (i = 0; i < this.items.length; i++) {
		this.wrapEl.childNodes[0].appendChild(this.items[i].el);
		if (this.items[i].thumbnailEl) {
			this.wrapEl.childNodes[1].appendChild(this.items[i].thumbnailEl);
		}
	}
	
	this.wrapEl.onmouseover = function() {
		clearTimeout(_self.timer);
		_self.pause = true;
	};
	
	this.wrapEl.onmouseout = function() {
		_self.pause = false;
		if (_self.items[_self.currentItem].fadeState == 'visible') {
			_self.timer = setTimeout(function() {
				_self.startFade();
			}, _self.duration);
		}
	};
	
	this.switchTo = function(item) {
		clearTimeout(_self.timer);
		clearTimeout(_self.fadeTimer);
		
		_self.pause = true;
		
		_self.items[_self.currentItem].el.style.opacity = 0;
		_self.items[_self.currentItem].el.style.display = "none";
		_self.items[_self.currentItem].el.style.filter = 'alpha(opacity = 0)';
		_self.items[_self.currentItem].fadeState = 'invisible';
		_self.items[_self.currentItem].thumbnailEl.className = 'rotator_item_thumb inactive';
		
		_self.currentItem = item;
		
		_self.items[_self.currentItem].el.style.opacity = 1;
		_self.items[_self.currentItem].el.style.display = "block";
		_self.items[_self.currentItem].el.style.filter = 'alpha(opacity = 100)';
		_self.items[_self.currentItem].fadeState = 'visible';
		_self.items[_self.currentItem].thumbnailEl.className = 'rotator_item_thumb active';
	};
	
	this.start = function() {
		_self.timer = setTimeout(function() {
			_self.startFade();
		}, _self.duration - 2000);
	};
	
	this.startFade = function() {
		if (_self.items[_self.currentItem].fadeState == null) {
			if (_self.items[_self.currentItem].el.style.opacity == 1 || _self.items[_self.currentItem].el.style.opacity == '1') {
				_self.items[_self.currentItem].fadeState = 'visible';
			} else {
				_self.items[_self.currentItem].fadeState = 'invisible';
			}
		}

		_self.items[_self.currentItem].fadeState = _self.items[_self.currentItem].fadeState == 'visible' ? 'fadeout' : 'fadein';
		
		if (_self.items[_self.currentItem].fadeState == 'fadein') {
			if (_self.items[_self.currentItem].thumbnailEl) {
				_self.items[_self.currentItem].thumbnailEl.className = 'rotator_item_thumb active';
			}
			_self.items[_self.currentItem].el.style.display = 'block';
		}
		
		_self.items[_self.currentItem].fadeTimeLeft = 1000;
		_self.fade(new Date().getTime());
	};
	
	this.fade = function(lastTick){
		var currentTick = new Date().getTime();
		var elapsedTicks = currentTick - lastTick;

		if (_self.items[_self.currentItem].fadeTimeLeft <= elapsedTicks) {
			clearTimeout(_self.fadeTimer);
			
			_self.items[_self.currentItem].el.style.opacity = _self.items[_self.currentItem].fadeState == 'fadein' ? 1 : 0;
			_self.items[_self.currentItem].el.style.filter = 'alpha(opacity = ' + (_self.items[_self.currentItem].fadeState == 'fadein' ? '100' : '0') + ')';
			_self.items[_self.currentItem].fadeState = _self.items[_self.currentItem].fadeState == 'fadein' ? 'visible' : 'invisible';

			// If the loop has reached its end and is now invisible, then start fading in the next banner
			if (_self.items[_self.currentItem].fadeState == 'invisible') {
				_self.items[_self.currentItem].el.style.display = 'none';
				if (_self.items[_self.currentItem].thumbnailEl) {
					_self.items[_self.currentItem].thumbnailEl.className = 'rotator_item_thumb inactive';
				}
				_self.currentItem = _self.currentItem >= _self.items.length - 1 ? 0 : _self.currentItem + 1;
				_self.startFade();
			} else if (!_self.pause){
				_self.timer = setTimeout(function() {
					_self.startFade();
				}, _self.duration);
			}
			return;
		}
	 
		// The fade loop is continuing
		_self.items[_self.currentItem].fadeTimeLeft -= elapsedTicks;
	  
		var newOpVal = _self.items[_self.currentItem].fadeTimeLeft / 1000;
	  
		if (_self.items[_self.currentItem].fadeState == 'fadein') { newOpVal = 1 - newOpVal};
	
		_self.items[_self.currentItem].el.style.opacity = newOpVal;
		_self.items[_self.currentItem].el.style.filter = 'alpha(opacity = ' + (newOpVal * 100) + ')';
	
		_self.fadeTimer = setTimeout(function(){
			_self.fade(currentTick);
		}, 33);
	};
};
