/*
Sky.Carousel 
copyright by MySign AG (http://www.mysign.ch), Christian Troller
depencies: Prototype 1.6
           script.aculo.us 1.8.1 effects
*/

// creating namespace
var Sky;
if ( !Sky ) Sky = {};

Sky.Carousel = Class.create();

Sky.Carousel._REQUIRED_PROTOTYPE = '1.6.0.2';
Sky.Carousel._REQUIRED_SCRIPTACULOUS_EFFECTS = '1.8.1';

Sky.Carousel.prototype =
{
	initialize: function( id, prevButtonId, nextButtonId, opts ) 
	{
		// checking Sky.PrototypeExtensions
		if( Object.isUndefined( Sky.PrototypeExtensions ) )
		{
			throw( "Sky.Carousel requires the Sky.PrototypeExtensions JavaScript framework" );
		}
		// checking Prototype
		if( !Sky.PrototypeExtensions.isPrototypeLoaded( Sky.Carousel._REQUIRED_PROTOTYPE ) )
		{
			throw( "Sky.Carousel requires the Prototype JavaScript framework >= " + Sky.Carousel._REQUIRED_PROTOTYPE );
		}
		// checking script.aculo.us effects
		if( !Sky.PrototypeExtensions.isScriptaculousEffectsLoaded( Sky.Carousel._REQUIRED_SCRIPTACULOUS_EFFECTS ) )
		{
			throw( "Sky.Carousel requires the script.aculo.us effects JavaScript framework >= " + Sky.Carousel._REQUIRED_SCRIPTACULOUS_EFFECTS );
		}
	
		this.options = 
		{
			elementTag:			'div',
			elementTagClass:	'slideElement',
			slideTime:			1,
			slideTransition:	Effect.Transitions.sinoidal,
			delay:				0,
			autoSlide:			0, // time for auto slide (0=off)
			firstIndex:			0,
			autoDisable:		true,
			endlessCarousel:	false,
			disableClass:		'slideDisable',
			getNrOfElements:	function(){ return 1; },
			reverse:			false // false = move from right to left (slide to next); true = move from left to right (slide to previous)
		};
		
		Object.extend(this.options, opts || {});
		
		this.id = id;
		this.prevButtonId = prevButtonId;
		this.nextButtonId = nextButtonId;
		this.currentIndex = this.options.firstIndex;
		this.autoSlider = null;
		
		if ( this.options.endlessCarousel )
		{
			 this.currentIndex += this.options.getNrOfElements();
			
			var elements = $( this.id ).select( this.options.elementTag + '.' + this.options.elementTagClass );
			var elementsWidth = 0;
			elements.each( function( value )
				{
					elementsWidth += value.getWidth();
				}
			);
			
			var firstElem = elements.first();
			var lastElem = elements.last();
			
			var index = elements.length;
			for ( var i = 0; i < this.options.getNrOfElements(); i++ )
			{
				var tmpElem = elements[i].clone( true );
				lastElem.insert( { after: tmpElem } );
				lastElem = tmpElem;
				
				tmpElem = elements[index-1].clone( true );
				firstElem.insert( { before: tmpElem } );
				elementsWidth += tmpElem.getWidth();
				firstElem = tmpElem;
				index--;
			}
			
			this.leftLastPX = elementsWidth;
		}
		
		var elements = $( this.id ).select( this.options.elementTag + '.' + this.options.elementTagClass );
		var leftPX = 0;
		this.slideElements = $H();
		elements.each( function( value, index )
			{
				this.slideElements.set( index, value );
				if ( index < this.currentIndex )
				{
					leftPX += value.getWidth();
				}
			}.bind( this )
		);
		$(this.id).setStyle( 'left: -' + leftPX + 'px;' );
		
		if( this.nextButtonId != null && $( this.nextButtonId ) != null )
		{
			$( this.nextButtonId ).observe( 'click', function( event )
													{
														if( this.autoSlider != null )
														{
															this.autoSlider.stop();
														}
														this.next();
														Event.stop( event );
													}.bind( this ) );
		}
		
		if( this.prevButtonId != null && $( this.prevButtonId ) != null )
		{
			$( this.prevButtonId ).observe( 'click', function( event )
													{
														if( this.autoSlider != null )
														{
															this.autoSlider.stop();
														}
														this.previous();
														Event.stop( event );
													}.bind( this ) );
		}
		
		if( this.options.autoDisable && ( this.options.firstIndex == 0 || this.options.firstIndex == this.slideElements.values().size() ) )
		{
			if( this.prevButtonId != null && $( this.prevButtonId ) != null )
			{
				$( this.prevButtonId ).addClassName( this.options.disableClass );
			}
			if( this.nextButtonId != null && $( this.nextButtonId ) != null )
			{
				$( this.nextButtonId ).addClassName( this.options.disableClass );
			}
			this._autoDisable( this.options.firstIndex );
		}
		
		if ( this.options.autoSlide > 0 )
		{
			setTimeout( this._startAutoSlide.bind( this ), this.options.delay * 1000 );
		}
	},
	
	_startAutoSlide: function ()
	{
		if ( !this.options.reverse )
		{
			this.next();
		}
		else
		{
			this.previous();
		}
		this.autoSlider = new PeriodicalExecuter( function() {
			if ( !this.options.reverse )
			{
				this.next();
			}
			else
			{
				this.previous();
			}
		}.bind( this ), this.options.autoSlide );
	},
	
	next: function()
	{
		var nextIndex = this.currentIndex + this.options.getNrOfElements();
		this._move( nextIndex );
		return ( nextIndex < this.slideElements.size() );
	},
	
	previous: function()
	{
		var previousIndex = this.currentIndex - this.options.getNrOfElements();
		this._move( previousIndex );
		return ( previousIndex > 0 );
	},
	
	_move: function( toIndex )
	{
		if( this.slide )
		{
			this.slide.finish();
		}
		
		if( this.options.endlessCarousel )
		{
			if ( toIndex < this.options.getNrOfElements() )
			{
				this.currentIndex = this.slideElements.size() - this.options.getNrOfElements();
				toIndex = this.currentIndex - this.options.getNrOfElements();
				$(this.id).setStyle( 'left: -' + this.leftLastPX + 'px;' );
			}
			else if ( toIndex >= this.slideElements.size() - 1 )
			{
				this.currentIndex = 0;
				toIndex = this.options.getNrOfElements();
				$(this.id).setStyle( 'left: 0px;' );
			}
		}
		
		if( this.slideElements.get( toIndex ) )
		{
			var offsetX = 0;
			if( ( this.currentIndex - toIndex ) < 0 )
			{
				var tmpIndex = this.currentIndex;
				while ( tmpIndex < toIndex )
				{
					offsetX -= this.slideElements.get( tmpIndex ).getWidth();
					tmpIndex++;
				}
			}
			else
			{
				var tmpIndex = toIndex;
				while ( tmpIndex < this.currentIndex )
				{
					offsetX += this.slideElements.get( tmpIndex ).getWidth();
					tmpIndex++;
				}
			}
			
			this.slide = new Effect.Parallel( [
					new Effect.Move( $( this.id ), {
						x: offsetX,
						y: 0,
						sync: true,
						transition: this.options.slideTransition
					} )
				], {
					duration: this.options.slideTime,
					transition: this.options.slideTransition
				}
			);
			
			if( this.options.autoDisable )
			{
				this._autoDisable( toIndex );
			}
			
			this.currentIndex = toIndex;
		}
	},
	
	_autoDisable: function( toIndex )
	{
		if( toIndex == 0 )
		{
			if( this.prevButtonId != null && $( this.prevButtonId ) != null )
			{
				$( this.prevButtonId ).addClassName( this.options.disableClass );
			}
			
			if( this.slideElements.values().size() > this.options.getNrOfElements() && this.nextButtonId != null && $( this.nextButtonId ) != null )
			{
				$( this.nextButtonId ).removeClassName( this.options.disableClass );
			}
		}
		else if( toIndex >= this.slideElements.values().size() - this.options.getNrOfElements() )
		{
			if( this.nextButtonId != null && $( this.nextButtonId ) != null )
			{
				$( this.nextButtonId ).addClassName( this.options.disableClass );
			}
			
			if( this.prevButtonId != null && $( this.prevButtonId ) != null )
			{
				$( this.prevButtonId ).removeClassName( this.options.disableClass );
			}
		}
		else
		{
			if( this.slideElements.values().size() > ( toIndex + this.options.getNrOfElements() ) && this.nextButtonId != null && $( this.nextButtonId ) != null )
			{
				$( this.nextButtonId ).removeClassName( this.options.disableClass );
			}
			
			if( this.prevButtonId != null && $( this.prevButtonId ) != null )
			{
				$( this.prevButtonId ).removeClassName( this.options.disableClass );
				
			}
		}
	}
}

// For compatibility reasons
var My;
if( !My ) My = {};
My.Carousel = Sky.Carousel;
