
/**
 * News Swapper class
 */
var NewsSwapper = Class.create();
NewsSwapper.prototype = {
	/**
	 * Constructor - called every time you create a new news swapper object
	 *
	 * @param id|element Element or ID of Element whose innerHTML will be replaced with news.
	 * @param string Prefix for article urls ie; http://www.mysite.com/articles/
	 * @param array Array of article files - these will be prefixed with the article_url_prefix
	 * @param float Number of seconds with .001 precision
	 * @param float Number of seconds with .001 precision for fade transition
	 * @param float Fade amount per interval
	 */
	initialize: function (news_swap, article_url_prefix, articles, interval, fade_interval, fade_amount)
	{
		/* store the element for later */
		this.news_swap = $(news_swap);

		/* store article_url_prefix for later */
		this.article_url_prefix = article_url_prefix; 

		/* store the articles for later */
		this.articles = articles;

		/* store the interval for later */
		this.interval = interval;

		/* establish counter for which one to show */
		this.current_article = 0;

		/* keep track of timer for starting/stoping */
		this.timer = false;

		/* fire off the first swap to get content */
		this.swap();

		//setup fade stuff after initial swap so that initial swap doesnt fade in

		/* keep track of fade interval */
		this.fade_interval = fade_interval;

		/* keep track of fade amount */
		this.fade_amount = fade_amount;

		/* default opacity is visible */
		this.opacity = 100;

		/* keep track of timer for fading */
		this.fade_timer = false;


	},

	/**
	 * Starts the news swapping
	 */
	start: function()
	{

		// make sure we arent already running
		if (this.timer)
		{
			return;
		}

		this.timer = setInterval(this.swap.bind(this), this.interval * 1000);

	},

	/**
	 * Swaps the article
	 */
	swap: function()
	{
		//if we need to fade out before swapping, do it
		if (this.fade_interval)
		{
			this.do_fade_out_swap();
		}
		else	//otherwise, just do a regular swap
		{
			this.do_swap();
		}
	},

	/**
	 * Fades out and then swaps the article
	 */
	do_fade_out_swap: function()
	{
		this.fade_out(this.do_swap.bind(this));
	},

	/**
	 * Does a swap on the article
	 */
	do_swap: function()
	{
		//if we run out of articles, start over
		if (this.current_article >= this.articles.length)
		{
			this.current_article = 0;
		}

		var url = this.article_url_prefix + this.articles[this.current_article];

		var request = new Ajax.Updater(
			this.news_swap,
			url,
			{
				method: 'get',
				onSuccess: this.swap_done.bind(this)
			}
		);

		this.current_article++;
	},

	/**
	 * Gets called when a swap finishes (onLoad)
	 */
	swap_done: function()
	{
		//if necessary, fade in
		if (this.fade_amount)
		{
			this.fade_in();
		}
	},

	/**
	 * Stops the news swapping
	 */
	stop: function()
	{
		if (!this.timer)
		{
			return;
		}

		//clear the timer
		clearInterval(this.timer);

		//set the timer to false for additional checks
		this.timer = false;
	},

	/**
	 * Goes backwards one news swap
	 */
	rewind: function()
	{
		//keep track of whether or not its currently running
		var running = this.timer;

		//this eliminates racing between timer and clicking rewind
		if (running)
		{
			this.stop();
		}

		//when displayed, the article number is increased by 1. to get to previous, decrease by 2
		this.current_article = this.current_article - 2;

		//if the resulting article is less than 0, move it back from the end of the list by the amount less than 0
		//index starts at 0 but length always leads by 1
		if (this.current_article < 0)
		{
			this.current_article = this.articles.length + this.current_article;
		}

		//call swap and the previous article should be displayed
		this.swap();

		//if it was running and we stopped it to avoid a race, start it back up
		if (running)
		{
			this.start();
		}

	},

	/**
	 * Goes forward one news swap
	 */
	forward: function()
	{

		//keep track of whether or not its currently running
		var running = this.timer;

		//this eliminates racing between timer and clicking forward
		if (running)
		{
			this.stop();
		}

		//swap function increments it for us :)
		this.swap();

		//if it was running and we stopped it to avoid a race, start it back up
		if (running)
		{
			this.start();
		}
	},

	/**
	 * Recursive function called to fade out
	 * @param function callback to be called when fade out finishes
	 */
	fade_out: function(cb)
	{

		//stop any executing fade when starting this one
		if (this.fade_timer)
		{
			clearInterval(this.fade_timer);
		}

		//call an anon function that handles fade logic every fade_interval seconds
		this.fade_timer = setInterval
		(
			function () 
			{

				//we are done
				if (this.opacity <= 0)
				{
					clearInterval(this.fade_timer);

					//if theres a callback, call it
					if (cb)
					{
						cb();
					}
					return;
				}

				//record new opacity
				this.opacity = this.opacity - this.fade_amount;

				//set opacity
				this.set_opacity(this.news_swap, this.opacity);

			}.bind(this), 
			this.fade_interval * 1000
		);

	}
	,

	/**
	 * Recursive function called to fade in
	 */
	fade_in: function()
	{

		//stop any executing fade when starting this one
		if (this.fade_timer)
		{
			clearInterval(this.fade_timer);
		}

		//call an anon function that handles fade logic every fade_interval seconds
		this.fade_timer = setInterval
		(
			function () 
			{

				//we are done
				if (this.opacity >= 100)
				{
					clearInterval(this.fade_timer);
					return;
				}

				//record new opacity
				this.opacity = this.opacity + this.fade_amount;

				//set opacity
				this.set_opacity(this.news_swap, this.opacity);

			}.bind(this), 
			this.fade_interval * 1000
		);

	},

	/**
	 * Sets opacity amount on an object
	 *
	 * @param object Object to set opacity on
	 * @param integer Opacity value to set 0-100 invisible-opaque
	 */
	set_opacity: function(obj, opacity)
	{
		opacity = (opacity == 100)?99.999:opacity;
  
		// IE/Win
		obj.style.filter = "alpha(opacity:"+opacity+")";
  
		// Safari<1.2, Konqueror
		obj.style.KHTMLOpacity = opacity/100;
	 
		// Older Mozilla and Firefox
		obj.style.MozOpacity = opacity/100;
	 
		// Safari 1.2, newer Firefox and Mozilla, CSS3
		obj.style.opacity = opacity/100;

	},
	
	/**
	 * Makes the object fully visible
	 */
	show: function()
	{
		this.opacity = 100;
		this.set_opacity(this.news_swap, this.opacity);
	},

	/**
	 * Makes the object invisible
	 */
	hide: function()
	{
		this.opacity = 0;
		this.set_opacity(this.news_swap, this.opacity);
	}

};

