/**
 * Horizontal Slideshow Class
 *
 * @author slemoigne@agenceinteractive.com
 *
 * @version 1.1 - 2009-03-23
 *
 * modified by slemoigne v1.1 2009-03-23
 *		- class implement event
 *		- add event on currentElement ok
 *		- add var bChangeElement
 *
 * Use mootools 1.2
 */

var HorizontalSlideshow = new Class({

	Implements: [Events, Options],

	/**
	 * Options
	 *
	 */
	options : {
		//Redefine class
		css : {
			navigation_on 	: 'on',
			navigation_off 	: 'off',
			left_arrow		: 'left_arrow',
			right_arrow		: 'right_arrow',
			element			: 'element'
		},
	
		//Active or not navigation
		navigation : {
			active			: true,
			direction		: 'auto' //left, right, auto
		},
	
		//Scrolling
		move : {
			duration		: 500,
			transition		: Fx.Transitions.Sine.easeOut
		},
	
		//Auto_scrolling - time in millisecond
		auto_scrolling : {
			active			: true,
			period			: 1000,
			period_restart	: 10000,
			direction		: 'right' //left, right
		}	
	},
	
	/**
	 * Constuctor
	 *
	 * @param string 	- id of slideshow
	 * @param string 	- id of content
	 * @param string 	- id of block which must move
	 * @param string 	- id of navigation block
	 * @param array		- options
	 */
	initialize: function(sSlideshow, sContent, sBlock, sNavigation, options) {
		
		//init options
		this.setOptions(options);
		
		this.sSlideshow = sSlideshow;
		this.sContent = sContent;
		this.sBlock = sBlock;
		this.sNavigation = sNavigation;
		this.bChangeElement = true;
		
		this.iCurrentElement = 0;
		//calculation step of move
		this.iStep = $$('#' + this.sBlock + ' .' + this.options.css.element)[0].getSize().x;
		//Nb of block element
		this.iNbElement = $$('#' + this.sBlock + ' .' + this.options.css.element).length;
		
		this.oMove = null;
		
		this.initElement();
		this.initMove();
		this.initEvent();
		
		//start auto scrolling
		if ( this.options.auto_scrolling.active )
		{
			this.period = null;
			this.timer = null;
			this.startPeriod();
		}
	},
	
	/**
	 * Init element
	 *
	 */
	initElement: function() {
		//add id on block element
		var i = 0;
		var sCssSelector = '#' + this.sBlock + ' .' + this.options.css.element;
		$$(sCssSelector).each(function(el){
			el.id = this.sBlock + '_' + this.options.css.element + '_' + i;
			i++;
		}.bind(this));
		
		//if navigation is active
		if ( this.options.navigation.active )
		{
			//add id on navigation element
			i = 0;
			sCssSelector = '#' + this.sNavigation + ' .' + this.options.css.element;
			$$(sCssSelector).each(function(el){
				el.id = this.sNavigation + '_' + this.options.css.element + '_' + i;
				i++;
			}.bind(this));
		}
		
		//inject at the end the first block element to do a loop effect
		var oCloneFirstElement = $(this.sBlock + '_' + this.options.css.element + '_0').clone();
		oCloneFirstElement.id = this.sBlock + '_' + this.options.css.element + '_last';
		oCloneFirstElement.inject($(this.sBlock));
	},
	
	/**
	 * Init move - create move effect
	 *
	 */
	initMove: function() {
		this.oMove = new Fx.Tween(
			this.sBlock, 
			{
				wait : false, 
				transition : this.options.move.transition,
				duration : this.options.move.duration
			}
		);
	},
	
	/**
	 * Add event on the different element
	 *
	 */
	initEvent: function() {
		//Add event on left arrow
		var sLeftArrow = '#' + this.sSlideshow + ' .' + this.options.css.left_arrow;
		$$(sLeftArrow).addEvent('click', function(){
			if ( this.bChangeElement )
			{
				this.leftMove();
				if ( this.options.auto_scrolling.active )
					this.stopPeriodRestart();
			}
		}.bind(this));
		
		//Add event on right arrow
		var sRightArrow = '#' + this.sSlideshow + ' .' + this.options.css.right_arrow;
		$$(sRightArrow).addEvent('click', function(){
			if ( this.bChangeElement )
			{
				this.rightMove();
				if ( this.options.auto_scrolling.active )
					this.stopPeriodRestart();
			}
		}.bind(this));
		
		//Add event on navigation if active
		if ( this.options.navigation.active )
		{
			var sNavigationElement = '#' + this.sNavigation + ' .' + this.options.css.element;
			$$(sNavigationElement).each(function(oEl){
				oEl.addEvent('click', function(sEl){
					var sNum = sEl.replace(
						this.sNavigation + '_' + this.options.css.element + '_',
						''
					);
					var iNum = sNum.toInt();
					this.moveToElement(iNum);
					if ( this.options.auto_scrolling.active )
						this.stopPeriodRestart();
				}.bind(this, oEl.id));
			}.bind(this));
		}
	},
	
	/**
	 * Left Move
	 *
	 */
	leftMove: function() {
		//loop
		if ( this.iCurrentElement == 0 )
		{
			$(this.sBlock).setStyle('left', -(this.iNbElement * this.iStep));
			this.iCurrentElement = this.iNbElement;
		}
		
		//get current position
		var iPosition = $(this.sBlock).getPosition($(this.sContent)).x;
		//move
		this.oMove.start('left', iPosition, -this.iCurrentElement * this.iStep + this.iStep);
		//update current element
		this.iCurrentElement--;
		this.changeICurrentElement();
		
		//if navigation is active update it
		if ( this.options.navigation.active )
			this.updateNavigation();
	},
	
	/**
	 * Right Move
	 *
	 */
	rightMove: function() {
		//loop
		if ( this.iCurrentElement == this.iNbElement )
		{
			$(this.sBlock).setStyle('left', '0');
			this.iCurrentElement = 0;
		}
		
		//get current position
		var iPosition = $(this.sBlock).getPosition($(this.sContent)).x;
		//move
		this.oMove.start('left', iPosition, -this.iCurrentElement * this.iStep - this.iStep);
		//update current element
		this.iCurrentElement++;
		this.changeICurrentElement();
		
		//if navigation is active update it
		if ( this.options.navigation.active )
			this.updateNavigation();
	},
	
	/**
	 * Update navigation
	 *
	 */
	updateNavigation: function() {
		//replace on class by off class
		var sCssSelector = '#' + this.sNavigation + ' .' + this.options.css.navigation_on;
		$$(sCssSelector).addClass(this.options.css.navigation_off);
		$$(sCssSelector).removeClass(this.options.css.navigation_on);
		
		//get number of current element
		var iCurrent = this.iCurrentElement
		if ( iCurrent == this.iNbElement )
			iCurrent = 0;
			
		//add class 'on' on current navigation element 
		var sIdNavigation = this.sNavigation + '_' + this.options.css.element + '_' + iCurrent;
		$(sIdNavigation).addClass(this.options.css.navigation_on);
	},
	
	/**
	 * Move to an element
	 *
	 * @param int - num of the element
	 */
	moveToElement: function(iNum) {
		if ( iNum >= this.iNbElement )
			iNum = 0;
		
		var sDirection = this.options.navigation.direction;
		if ( sDirection != 'left' && sDirection != 'right' )
		{
			if ( iNum < this.iCurrentElement )
				sDirection = 'left';
			else
				sDirection = 'right';
		}
		
		while(this.iCurrentElement != iNum)
		{
			switch(sDirection)
			{
				case 'left':
					this.leftMove();
					break;
				case 'right':
					this.rightMove();
					break;
				default:
					this.rightMove();
			}
		}
	},
	
	/**
	 * Jump to element
	 *
	 */
	jumpToElement: function(iNum) {
		if ( iNum >= this.iNbElement )
			iNum = 0;
			
		$(this.sBlock).setStyle(
			'left',
			-iNum * this.iStep
		);
		this.iCurrentElement = iNum;
		
		if( this.options.navigation.active )
			this.updateNavigation();
	},
	
	/**
	 * Start call periodical move
	 *
	 */
	startPeriod: function() {
		if ( this.options.auto_scrolling.direction == 'left' )
		{
			this.period = this.leftMove.periodical(
				this.options.auto_scrolling.period,
				this
			);
		}
		
		if ( this.options.auto_scrolling.direction == 'right' )
		{
			this.period = this.rightMove.periodical(
				this.options.auto_scrolling.period,
				this
			);
		}
	},
	
	/**
	 * Stop periodical move and start it after
	 *
	 */
	stopPeriodRestart: function() {
		$clear(this.period);
		$clear(this.timer);
		this.timer = this.startPeriod.delay(
			this.options.auto_scrolling.period_restart,
			this
		);
	},
	
	/**
	 * Stop periodical move
	 *
	 */
	stopPeriod: function() {
		$clear(this.period);
		$clear(this.timer);
	},
	
	/**
	 * EVENTS
	 */
	changeICurrentElement: function(sId) {
		this.fireEvent('changeICurrentElement', sId);
	}
	
});
