/*
 * jQuery ListRotator v1.2
 * http://jquery.com/
 *
 * Copyright (c) 2009-2010 Jim Isaacs
 * http://jidd.jimisaacs.com/
 * Dual licensed under the MIT and GPL licenses.
 * http://docs.jquery.com/License
 *
 * Date: 10-12-2009 (Mon, 12 Oct 2009)
 * Updated: 01-11-2010 (Mon, 11 Jan 2010)
 * Revision: 4
 */

var ListRotator = function(total) {
	// VARIABLES
	/**
	 * @ignore Used internally
	 */ 
	this._intervalID = null;
	/**
	 * @var object _flags Internal object holding all the flags available for enabling and disabling
	 */
	this._flags = {};
	/**
	 * @var int currentIndex The index currently selected in the rotation
	 */
	this.currentIndex = 0;
	/**
	 * @var int total Amount available in the rotation
	 */
	this.total = total;
	/**
	 * @var interval The interval of the timer in milliseconds
	 */
	this.interval = 1000;
	/**
	 * @var int currentInterval The current interval as an integer
	 */
	this.currentInterval = 0;
	/**
	 * @var int maxInterval The max intervals as an integer
	 */
	this.maxInterval = 5;
	/**
	 * @var boolean playing Whether the interval is playing or not
	 */
	this.playing = false;
	// METHODS
	/**
	 * Trigger an event through jQuery (this is the only dependency on jQuery in this file.
	 * @param string event The event string to trigger through jQuery
	 * @return ListRotator
	 */
	this.trigger = function() {
		var event = arguments[0];
		jQuery(this).trigger(event);
		return this;
	};
	/**
	 * Get a boolean flag by name
	 * @param string name The name of the flag
	 * @return boolean
	 */
	this.getFlag = function(name) {
		if( name in this._flags ) return this._flags[name];
		return this._flags[name] = false;
	};
	/**
	 * Set a boolean flag by name
	 * @param string name The name of the flag
	 * @param boolean value The value of the flag
	 * @return ListRotator
	 */
	this.setFlag = function(name, value) {
		if(value) {
			if(!this.getFlag(name)) {
				this._flags[name] = true;
				return this.trigger(name+'Enabled');
			}
		} else {
			if(this.getFlag(name)) {
				this._flags[name] = false;
				return this.trigger(name+'Disabled');
			}
		}
		return this;
	};
	/**
	 * Selects an index and triggers the change event
	 * @param int index The index to select
	 * @param boolean force If true it triggers the change event regardless of an actual change
	 * @return ListRotator
	 */
	this.selectIndex = function(index) {
		if(this.getFlag('loop')) {
			index = (index < 0) ? this.total-1 : 0;
			index = (index > this.total-1) ? 0 : this.total-1;
		} else {
			index = (index < 0) ? 0 : index;
			index = (index > this.total-1) ? this.total-1 : index;
		}
		if(this.currentIndex == index && !arguments[1]) return this;
		if( !this.getFlag('loop') ) {
			this.setFlag('play', (index < this.total-1));
			this.setFlag('next', (index < this.total-1));
			this.setFlag('previous', (index > 0));
		} else if( index == 0 || index == this.total-1) {
			this.stop();
		}
		this.currentIndex = index;
		return this.trigger('change'); 
	};
	/**
	 * Selects the next available index
	 * @return ListRotator
	 */
	this.next = function() {
		if(!this.getFlag('next')) return this;
		return this.selectIndex(this.currentIndex+1);
	};
	/**
	 * Selects the previous available index
	 * @return ListRotator
	 */
	this.previous = function() {
		if(!this.getFlag('previous')) return this;
		this.selectIndex(this.currentIndex-1);
	};
	/**
	 * Starts the timer and triggers the play event
	 * While the timer is playing it triggers the interval event
	 * @return ListRotator
	 */
	this.play = function() {
		if(this.playing || !this.getFlag('play')) return this;
		this.playing = true;
		this.currentInterval = 0;
		// start the timer
		this._intervalID = window.setInterval( function(obj) {
			obj.currentInterval++;
			obj.trigger('interval'); 
			if ( obj.currentInterval == obj.maxInterval ) {
				obj.currentInterval = 0;
				obj.next();
			}
		}, this.interval, this );
		return this.trigger('play'); 
	};
	/**
	 * Stops the timer and triggers the stop event
	 * @return ListRotator
	 */
	this.stop = function() {
		if(!this.playing) return this;
		this.playing = false;
		window.clearInterval( this._intervalID );
		return this.trigger('stop'); 
	};
	/**
	 * Initiates the ListRotator object setting the current index
	 * and forcing a trigger of the change event
	 * @return ListRotator
	 */
	this.init = function() {
		return this.selectIndex(this.currentIndex, true);
	}
}