function Stage (sId, iWidth, iHeight, iDuration) {
	var oContainer = false;
	var oContentContainer = false;
	var oNavContainer = false;
	var aLinks = new Array();
	var aContentElements = new Array ();
	var iActiveElement = false;
	var iNewActiveElement = false;
	var bAnimationRunning = false;
	var oQueue = function () {};
	var oPrevLink = false;
	var oNextLink = false;
	var bShowPrevLink = false;
	var bShowNextLink = false;
	var bPrevLinkAnimationRunning = false;
	var bNextLinkAnimationRunning = false;
	var oPrevLinkQueue = function () {};
	var oNextLinkQueue = function () {};
	var oContainerPosition = false;
	var oPE = false;
	
	Event.observe(window, 'load', init);
	
	function init ()
	{
		oContainer = $(sId);
		if(oContainer)
		{
			oContentContainer = oContainer.select('div')[0];
			aContentElements = oContainer.select('div.stage_content');
			oNavContainer = oContainer.select('ul.stage_nav')[0];
			
			oContainerPosition = getPosition(oContentContainer);
			
			oPrevLink = $('stage_prev');
			oNextLink = $('stage_next');
			
			oPrevLink.setStyle({top: ((iHeight - oPrevLink.getHeight()) / 2) + 'px'});
			oNextLink.setStyle({top: ((iHeight - oNextLink.getHeight()) / 2) + 'px'});
			
			oPrevLink.observe('click', setPrev);
			oNextLink.observe('click', setNext);
					
			oNavContainer.update('');
			
			for ( var i = 0; i < aContentElements.length; i++ )
			{
				var oTempLiElement = document.createElement('li');
				var oTempAElement = document.createElement('a');
				
				$(oTempAElement).update(i+1);
				$(oTempAElement).href = '#';
				$(oTempAElement).observe('click', setActiveHandler);
				
				$(oTempLiElement).insert(oTempAElement);
				$(oNavContainer).insert(oTempLiElement);
				
				aLinks[i] = oTempAElement;
			}
			
			oContentContainer.observe('mouseenter', mouseenterHandler);
			
			setNewActive (0);
			updateView();
			
			startPE();
		}
	}
	
	function setNewActive (iIndex)
	{
		iNewActiveElement = iIndex;
	}
	
	function setActiveHandler (event)
	{
		event.preventDefault();
		event.stopPropagation();
		oPE.stop();
		setNewActive ( getIndexFromLink (this) );
		updateView();
		startPE();
		return false;
	}
	
	function setPrev (event)
	{
		event.preventDefault();
		event.stopPropagation();
		
		iNewActiveElement = iActiveElement - 1;
		
		if (iNewActiveElement < 0)
		{
			iNewActiveElement = aContentElements.length-1;
		}
		
		updateView();
		
		return false;
	}
	
	function setNext (event)
	{
		if (event)
		{
			event.preventDefault();
			event.stopPropagation();
		}
		
		iNewActiveElement = iActiveElement + 1;
		
		if (iNewActiveElement >= aContentElements.length)
		{
			iNewActiveElement = 0;
		}
		
		updateView();
		
		return false;
	}
	
	function mouseenterHandler (event)
	{
		oPE.stop();
		oContentContainer.observe('mousemove', mousemoveHandler);
		oContentContainer.observe('mouseleave', mouseleaveHandler);
		oContentContainer.stopObserving('mouseenter', mouseenterHandler);
	}
	
	function mouseleaveHandler (event)
	{
		oContentContainer.stopObserving('mousemove', mousemoveHandler);
		oContentContainer.stopObserving('mouseleave', mouseleaveHandler);
		oContentContainer.observe('mouseenter', mouseenterHandler);
		
		hidePrevLink();
		hideNextLink();
		startPE();
	}
	
	function mousemoveHandler (event)
	{
		var iMouseX = false;
		
		iMouseX = event.pageX - oContainerPosition.x;
		
		if (iMouseX < iWidth/3)
		{
			showPrevLink();
		}
		else if (bShowPrevLink)
		{
			hidePrevLink();
		}
		
		if (iMouseX > 2*iWidth/3)
		{
			showNextLink();
		}
		else if (bShowNextLink)
		{
			hideNextLink();
		}
	}
	
	function showPrevLink ()
	{
		if (bPrevLinkAnimationRunning)
		{
			oPrevLinkQueue = showPrevLink;
		}
		else if (!bShowPrevLink)
		{
			bPrevLinkAnimationRunning = true;
			bShowPrevLink = true;
			new Effect.Morph(oPrevLink, { style: 'width: 50px;', duration: 0.5, afterFinish: function(){bPrevLinkAnimationRunning = false; oPrevLinkQueue(); oPrevLinkQueue = function(){};}});
		}
	}
	
	function hidePrevLink ()
	{
		if (bPrevLinkAnimationRunning)
		{
			oPrevLinkQueue = hidePrevLink;
		}
		else if (bShowPrevLink)
		{
			bPrevLinkAnimationRunning = true;
			bShowPrevLink = false;
			new Effect.Morph(oPrevLink, { style: 'width: 0;', duration: 0.5, afterFinish: function(){bPrevLinkAnimationRunning = false; oPrevLinkQueue(); oPrevLinkQueue = function(){};}});
		}
	}
	
	function showNextLink ()
	{
		if (bNextLinkAnimationRunning)
		{
			oNextLinkQueue = showNextLink;
		}
		else if (!bShowNextLink)
		{
			bNextLinkAnimationRunning = true;
			bShowNextLink = true;
			new Effect.Morph('stage_next', { style: 'width: 50px;', duration: 0.5, afterFinish: function(){bNextLinkAnimationRunning = false; oNextLinkQueue(); oNextLinkQueue = function(){};}});
		}
	}
	
	function hideNextLink ()
	{
		if (bNextLinkAnimationRunning)
		{
			oNextLinkQueue = hideNextLink;
		}
		else if (bShowNextLink)
		{
			bNextLinkAnimationRunning = true;
			bShowNextLink = false;
			new Effect.Morph('stage_next', { style: 'width: 0;', duration: 0.5, afterFinish: function(){bNextLinkAnimationRunning = false; oNextLinkQueue(); oNextLinkQueue = function(){};}});
		}
	}
	
	function updateView ()
	{
		if (iActiveElement !== iNewActiveElement)
		{
			if (bAnimationRunning)
			{
				oQueue = updateView;
			}
			
			else
			{
				bAnimationRunning = true;
				if (iActiveElement!==false)
				{
					new Effect.Fade(aContentElements[iActiveElement]);
					$(aLinks[iActiveElement]).removeClassName('active');
				}
				new Effect.Appear(aContentElements[iNewActiveElement], {afterFinish: function(){bAnimationRunning = false; oQueue();}});
				
				$(aLinks[iNewActiveElement]).addClassName('active');
				
				iActiveElement = iNewActiveElement;	
			}
		}
	}
	
	function startPE ()
	{
		oPE = new PeriodicalExecuter(function(){setNext();}, iDuration);
	}
	
	function getIndexFromLink (oLink)
	{
		for (var i = 0; i < aLinks.length; i++)
		{
			if (oLink == aLinks[i])
			{
				return i;
			}
		}
	}
	
	function getPosition ( oElement )
	{
		var oPosition = {x: 0, y: 0};
		
		while( oElement != null )
		{
			oPosition.y += oElement.offsetTop;
			oPosition.x += oElement.offsetLeft;
			oElement = oElement.offsetParent;
		}
		
		return oPosition;
	}
}