function Slideshow( params )
{
	// Check for required params
	if ( typeof params.width == "undefined" || typeof params.container_id == "undefined" )
	{
		alert( 'Slideshow is missing required parameters!' );
		return;
	}
	
	this.width = params.width;
	this.container_elem = $( '#' + params.container_id );
	
	this.tween_duration = ( typeof params.tween_duration == "undefined" ) ? 500 : params.tween_duration;
	this.tween_delay = ( typeof params.tween_delay == "undefined" ) ? 0 : params.tween_delay;
	this.hold_time = ( typeof params.hold_time == "undefined" ) ? 1000 : params.hold_time;
	this.followers = ( typeof params.followers == "undefined" ) ? null : params.followers;
	this.reset_on_stop = ( typeof params.reset_on_stop == "undefined" || ! params.reset_on_stop ) ? false : true;
	this.random = ( typeof params.random == "undefined" || ! params.random ) ? false : true;
	
	if ( typeof params.transitioner == "undefined" )
		this.moveSlide = Slideshow.slideTransition;
	else if ( typeof params.transitioner == "function" )
		this.moveSlide = params.transitioner;
	else if ( params.transitioner == 'filmstrip' )
		this.moveSlide = Slideshow.filmstripTransition;
	else if ( params.transitioner == 'fade' )
		this.moveSlide = Slideshow.fadeTransition;
	
	if ( typeof params.markers_id == "undefined" )
		this.markers = null;
	else
	{
		if ( typeof params.marker_toggle == "undefined" )
		{
			alert( 'You must specify a toggle function for your markers!' );
			return;
		}
		this.marker_toggle = params.marker_toggle;
		
		var markers = new Array( );
		$( '#' + params.markers_id ).children( ).each( function( )
		{
			$( this ).attr( 'markerState', 'off' );
			markers.push( $( this ) );
		} );
		this.markers = markers;
		
		this.marker_toggle( this.markers[ 0 ] );			
	}

	if ( typeof params.counter_id == "undefined" )
		this.counter = null;
	else
	{
		this.counter = $( '#' + params.counter_id );
		var counter_text = this.counter.html( );
		var i1 = counter_text.search( /_\d_/ );
		var i2 = ( counter_text.substring( i1+3, counter_text.length ).search( /_\d_/ ) ) + i1+2;
		
		this.counter_text_pre = counter_text.substring( 0, i1 );
		this.counter_text_mid = counter_text.substring( i1+3, i2+1 );
		this.counter_text_post = counter_text.substring( i2+4, counter_text.length );
	}


	var slides = new Array( );
	this.container_elem.children( ).each( function( )
	{
		slides.push( $( this ) );
	} );
	this.slides = slides;
	this.total_slides = slides.length;
	this.current_slide_index = this.random ? Math.round( Math.random( ) * (this.total_slides-1) ) : 0;
	
	if ( typeof params.align == "undefined" || params.align == "left" )
		this.slides[ this.current_slide_index ].css( "left", 0 );

	if ( this.counter != null )
		this.counter.html( this.counter_text_pre + '1' + this.counter_text_mid + this.slides.length + this.counter_text_post );
	
	this.timer = null;
	this.isPlaying = false;
}
Slideshow.prototype.start = function( )
{
	if ( ! this.isPlaying )
	{
		var self = this;
		this.isPlaying = true;
		this.timer = setInterval( function( ) { self.nextSlide( ); }, this.hold_time );
	}
};
Slideshow.prototype.stop = function( )
{
	this.isPlaying = false;
	clearInterval( this.timer );
	
	if ( this.reset_on_stop )
		this.gotoSlide( 0 );
};
Slideshow.prototype.gotoSlide = function( index )
{
	if ( this.current_slide_index != index )
	{
		var self = this;
		this.moveSlide( self, index );
		
		if ( this.markers != null )
		{
			this.marker_toggle( this.markers[ this.current_slide_index ] );
			this.marker_toggle( this.markers[ index ] );
		}

		if ( this.followers != null )
			for ( var i=0; i<this.followers.length; i++ )
				this.followers[ i ].gotoSlide( index );

		if ( this.counter != null )
			this.counter.html( this.counter_text_pre + ( index+1 ) + this.counter_text_mid + this.slides.length + this.counter_text_post );

		this.current_slide_index = index;
	}	
};

// Default transition is overflow:hidden, sliding
Slideshow.slideTransition = function( self, index )
{
	var current_slide = self.slides[ self.current_slide_index ]; 
	var next_slide = self.slides[ index ];
	
	next_slide.css( {
		"left": self.width
	} );
	current_slide.animate( { "left": -self.width }, self.tween_duration );
	next_slide.animate( { "left": 0 }, self.tween_duration );
};

// A Cross-fade transition
Slideshow.fadeTransition = function( self, index )
{
	var current_slide = self.slides[ self.current_slide_index ]; 
	var next_slide = self.slides[ index ];
	
	current_slide.css( {
		"left": 0,
		"alpha": 1,
		"z-index": 5
	} );
	next_slide.css( {
		"left": 0,
		"alpha": 0,
		"z-index": 1
	} );
	
	//current_slide.animate( { "alpha": 0 }, self.tween_duration );
	current_slide.fadeOut( self.tween_duration );
	next_slide.fadeIn( self.tween_duration );
	//next_slide.animate( { "alpha": 1 }, self.tween_duration );
};

// This transition is a film strip, overflow visible
Slideshow.filmstripTransition = function( self, index )
{
	var current_slide = self.slides[ self.current_slide_index ]; 
	var next_slide = self.slides[ index ];
	
	
	// Get our delta
	var curr_pos = current_slide.position( );
	var next_pos = next_slide.position( );

	var delta = curr_pos.left - next_pos.left + ( ( parseInt( current_slide.attr( 'width' ) ) - parseInt( next_slide.attr( 'width' ) ) ) / 2 );
	
	// Balance the # of slides
	var num_on_left = 0;
	var num_on_right = 0;
	var leftmost_index = 0;
	var leftmost_left = 0;
	for ( var i = 0; i < self.slides.length; i++ )
	{
		var this_pos = self.slides[ i ].position( );
		if ( this_pos.left < next_pos.left )
			num_on_left++;
		else if ( this_pos.left > next_pos.left )
			num_on_right++;
			
		if ( this_pos.left < leftmost_left )
		{
			leftmost_left = this_pos.left;
			leftmost_index = i;	
		}
	}
	
	var rightmost_index = leftmost_index - 1;
	if ( rightmost_index == -1 )
		rightmost_index = self.slides.length - 1;
		
//	alert( leftmost_index + ' ' + rightmost_index );
		
	var rightmost_pos = self.slides[ rightmost_index ].position( );
	var rightmost_left = rightmost_pos.left;
	
	if ( num_on_left > num_on_right )
	{
		var num_to_shift = num_on_left - num_on_right;
		
//		for ( var i = 1; i <= num_to_shift; i++ )
//		{
//			self.slides[ leftmost_index + i ].css( "left", rightmost_left + ( self.width * i ) );
//		}

		self.slides[ leftmost_index ].css( "left", rightmost_left + parseInt( self.slides[ rightmost_index ].attr( 'width' ) ) + 25 );
	}
	else if ( num_on_right > num_on_left )
	{
		var num_to_shift = num_on_right - num_on_left;
		
//		for ( var i = 1; i <= num_to_shift; i++ )
//		{
//			self.slides[ rightmost_index - i ].css( "left", leftmost_left - ( self.width * i ) );
//		}

		self.slides[ rightmost_index ].css( "left", leftmost_left - parseInt( self.slides[ rightmost_index ].attr( 'width' ) ) - 25 );
	}
	
	// Now shift everyone!
	for ( var i = 0; i < self.slides.length; i++ )
	{
		self.slides[ i ].animate( { "left": "+=" + delta }, self.tween_duration );
	}
};



Slideshow.prototype.nextSlide = function( )
{
	if ( this.current_slide_index < this.total_slides-1 )
		this.gotoSlide( this.current_slide_index + 1 );
	else
		this.gotoSlide( 0 );
};
Slideshow.prototype.prevSlide = function( )
{
	if ( this.current_slide_index > 0 )
		this.gotoSlide( this.current_slide_index - 1 );
	else
		this.gotoSlide( this.total_slides-1 );
};

