
/// Configurable variables. For intervals, 1000 = 1 second.

var linkScrollerWaitDuration = 7000; ///< Duration of idle time.
var linkScrollerScrollDuration = 1000; ///< How long to scroll for.
var linkScrollerScrollInterval = 10; ///< Interval when the scrolling animation is updates.

////////////////////////////////////////////////////////////////////////////////
/// linkScroller constructor
function linkscroll()
{
	/// Instance variable for callbacks.
	var instance = this;
	
	/// Get all of the stories. All stories have ids of the form
	/// "ls-story-n" where n is the number of the story.
	this.stories = e_enum("ls-story-");
	
	/// All of the stories should be in divs of the same height, otherwise
	/// scrolling would screw up.
	this.divHeight = conformY(this.stories);
	
	/// Set the wrapper div to the height of the story divs.
	e("ls-wrap").style.height = this.divHeight + 'px';
	
	/// Set the clipping div's clip region.
	e("ls-mask").style.clip = "rect(0px 198px " + this.divHeight + "px 0px)";
	
	/// Set the callback for the play / pause button.
	this.imgPlayPause = e("ls-play-pause");
	this.imgPlayPause.onclick = function() { instance.onPlayPauseClick(); } 
	
	/// Preload the play / pause images.
	this.imgPlay = new Image;
	this.imgPause = new Image;
	this.imgPlay.src = core_url + "/i/play.gif";
	this.imgPause.src = core_url + "/i/pause.gif";
	
	/// Set the callback for the next / prev buttons
	e("ls-next").onclick= function(){ instance.goToStoryByOffset(+1) };
	e("ls-previous").onclick= function(){ instance.goToStoryByOffset(-1) };
	
	/// Constants to compare to the 'status' variable.
	this.mode_scrolling = 1;
	this.mode_idling = 2;
	this.mode_paused = 3;
	
	/// Initial mode. The output should be set up so the first story is
	/// visible.
	this.currentStory = 0;
	this.status = this.mode_idling;
	
	/// Variables used during scrolling.
	this.pendingStory = -1;
	this.startedScrollingAt = -1;
	
	/// Initially the scroller will idle on the first story.
	this.startIdling();
}

////////////////////////////////////////////////////////////////////////////////
/// Play / pause button callback.
linkscroll.prototype.onPlayPauseClick = function()
{
	if(this.status == this.mode_paused)
	{
		/// Paused. Start scrolling immediately.
		this.startScrolling();
		
		/// Set the image to pause.
		this.imgPlayPause.src = this.imgPause.src;
	}
	else /// Playing.
	{
		/// Kill whatever interval is going on.
		clearInterval(this.interval);
		
		/// Set the mode and the image to play.
		this.status = this.mode_paused;
		this.imgPlayPause.src = this.imgPlay.src;
		
		/// Animating? Need to undo the animation (pauses on leaving story).
		if(this.status == this.mode_scrolling) this.enableAndDisable(this.currentStory, this.pendingStory);
	}
}

////////////////////////////////////////////////////////////////////////////////
/// Offset is only ever -1 or +1. Adds the offset to the current story index and
/// pauses the scroller.
linkscroll.prototype.goToStoryByOffset = function(offset)
{	
	if(this.status == this.mode_scrolling)
	{
		/// Animating. Depending on offset, hide or show the current and
		/// pending story.
		if(offset == -1) this.enableAndDisable(this.currentStory, this.pendingStory);
		else this.enableAndDisable(this.pendingStory, this.currentStory);	
	}
	else /// Not animating.
	{
		/// Add offset to current index and check the range.
		var goToIndex = this.currentStory + offset;
		if(goToIndex >= this.stories.length) goToIndex = 0;
		else if(goToIndex < 0) goToIndex = this.stories.length - 1;
		
		/// Hide current story and show new one.
		this.enableAndDisable(goToIndex, this.currentStory);
	}

	/// Set the mode and the play / pause button and clear interval.
	if(this.interval) clearInterval(this.interval);
	this.status = this.mode_paused
	this.imgPlayPause.src = this.imgPlay.src;	
}

////////////////////////////////////////////////////////////////////////////////
/// Sets the story at index 'enable' to visible, the story at index 'disable'
/// into oblivion. Also sets the currentStory index.
linkscroll.prototype.enableAndDisable = function(enable, disable)
{
	this.positionStoryDiv(enable, 0);
	if(this.disable != -1) this.positionStoryDiv(disable, -5000);
	
	/// Set the current story, and the div the indicates the current story.
	this.currentStory = enable;
	e("ls-current").innerHTML = this.currentStory + 1;
}

////////////////////////////////////////////////////////////////////////////////
/// Sets the style position of story at index 'index'. Only positions y
/// because that's all the scrolling animation cares about.
linkscroll.prototype.positionStoryDiv = function(index, y)
{
	this.stories[index].style.top = y + 'px';
}

////////////////////////////////////////////////////////////////////////////////
/// Wait until it is time to scroll...
linkscroll.prototype.startIdling = function()
{
	if(this.interval) clearInterval(this.interval);
	var instance = this;
	this_startScrolling = function() { instance.startScrolling(); } 
	this.interval = setInterval(this_startScrolling, linkScrollerWaitDuration);
	
	/// Keep track of the current mode.
	this.status = this.mode_idling;
}

////////////////////////////////////////////////////////////////////////////////
/// Start scrolling!
linkscroll.prototype.startScrolling = function()
{
	/// Identify and position the incoming story.
	this.pendingStory = (this.stories.length == (this.currentStory + 1)) ? 0 : this.currentStory + 1;
	this.positionStoryDiv(this.pendingStory, this.divHeight);
	
	/// Store the time the scrolling starts.
	var t = new Date();
	this.startedScrollingAt = t.getTime();
	
	/// Set up the scrolling callback
	if(this.interval) clearInterval(this.interval);
	var instance = this;
	this_scrollAnimationStep = function() { instance.scrollAnimationStep(); }
	this.interval = setInterval(this_scrollAnimationStep, linkScrollerScrollInterval);
	
	/// Keep track of the current mode.
	this.status = this.mode_scrolling;
}

////////////////////////////////////////////////////////////////////////////////
/// Called for each step of the scroll animation.
linkscroll.prototype.scrollAnimationStep = function()
{
	/// Get the time since the animation started.
	var t = new Date();
	var timeElapsed = t.getTime() - this.startedScrollingAt;
	
	/// If the configuration animation time has elapsed, end the animation
	if(linkScrollerScrollDuration <= timeElapsed)
	{
		/// Snap the story divs into their final position.
		this.enableAndDisable(this.pendingStory, this.currentStory);
		
		/// Wait until next time...
		this.startIdling();
	}
	else /// Still animating.
	{
		/// Use the cos() function to approximate a tween.
		var halfHeight = this.divHeight / 2;
		scrollAmount = parseInt((Math.cos((timeElapsed * Math.PI) / linkScrollerScrollDuration) * halfHeight) + halfHeight);
		
		/// Set the incoming story position.
		this.positionStoryDiv(this.pendingStory, scrollAmount);
		
		/// Set the outgoing story position.
		this.positionStoryDiv(this.currentStory, scrollAmount - this.divHeight);
	}
}







