// <![CDATA[

/**
 * jQuery.nastyShow() is a jQuery plugin providing keyboard-navigable slideshow.
 * 
 * @example $( '#slideshow' ).nastyShow();
 * @link    http://sixrevisions.com/tutorials/javascript_tutorial/create-a-slick-and-accessible-slideshow-using-jquery/
 * @link    http://starter.pixelgraphics.us/
 * @author  Romain Ruetschi <romain.ruetschi@gmail.com>
 * @license http://romac.github.com/files/BSD.txt New BSD License
 * @version 0.1
 */
( function( $ )
{
    $.nastyShow = function( container, options )
    {
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base        = this;
        
        /**
         * Initialize the plugin.
         */
        base.init = function()
        {
            // Override the default options with the supplied ones.
            base.options         = $.extend( {}, $.nastyShow.defaultOptions, options );
            
            // Access to jQuery and DOM versions of the slideshow.
            base.$container      = $( container );
            base.container       = container;
            
            // Add a reverse reference to the DOM object.
            base.$container.data( 'nastyShow', base );
            
            // Access to jQuery version of the slides.
            base.$slides         = base.$container.children();
            
            base.sizeFunc        = 'width';
            base.size            = 'width';
            base.margin          = 'marginLeft';
            base.vertical        = false;
            
            if( base.options.mode === 'vertical' ) {
                
                base.sizeFunc    = 'outerHeight';
                base.size        = 'height';
                base.margin      = 'marginTop';
                base.vertical    = true;
            }
            
            // Compute the slide width/height and number.
            base.slideSize      = base.$slides[ base.sizeFunc ]();
            base.slidesNumber   = base.$slides.length;
            base.innerSize      = base.slidesNumber * base.slideSize;
            
            // Init. the current position to 0.
            base.currentPosition = 0;
            
            // Is animating now ?
            base.animating       = false; 
            
            var styles = {
                'overflow' : 'hidden'
            };
            
            styles[ base.size ] = base.slideSize + 'px';
            
            base.$container.css( styles );
            
            delete styles;
            
            // Wrap all .slides with .slideInner div.
            base.$slides.wrapAll( '<div class="slideInner"></div>' );
            
            if( !base.vertical ) {
                
                // Float left to display horizontally.
                base.$slides.css( {
                    'float' : 'left'
                } );
            };
            
            // Set .slideInner width equal to total width of all slides
            base.$slideInner = base.$container.find( '.slideInner' ).css(
                base.size,
                base.slideSize * base.slidesNumber
            );
            
            // Create the buttons
            if( base.options.buttons ) {
                
                base.$buttons = $( base.options.buttons );
                
                for( var i = 0; i < base.$slides.length; i++ ) {
                    
                    var $slide  = base.$slides[ i ];
                    var $button = $( '<a id="slide-b-' + i + '">'
                                + '&nbsp;'
                                + '</a>' ).data( 'nastyShow-index', i );
                    
                    $button.attr( 'href', '#slide-' + i );
                    
                    $button.click( function( event )
                    {
                        event.preventDefault();
                        
                        var pos = parseInt( $( this ).data( 'nastyShow-index' ), 10 );
                        
                        base.move(
                            pos,
                            ( pos < base.currentPosition ) ? 'prev' : 'next'
                        );
                        
                        base.$buttons.children().removeClass( 'cur' ).eq( pos ).addClass( 'cur' );
                    } );
                    
                    base.$buttons.append( $button );
                }
                
                base.$buttons.find( 'a:first-child' ).addClass( 'cur' );
            }
        };
        
        /**
         * Move to the next slide.
         * 
         * @see    $.nastyShow.move
         * @return void
         */
        base.next = function()
        {
            var position = ( base.currentPosition + 1 ) % base.slidesNumber;
            
            base.move( position, ( base.options.rotate ) ? 'next' : false );
        };
        
        /**
         * Move to the previous slide.
         * 
         * @see    $.nastyShow.move
         * @return void
         */
        base.previous = function()
        {
            var position = base.currentPosition - 1;
            
            if( base.currentPosition === 0 ) {
                
                position = base.slidesNumber - 1;
            }
            
            base.move( position, ( base.options.rotate ) ? 'prev' : false );
        };
        
        /**
         * Move to another slide by its position.
         * 
         * @param integer position The position of the slide to move to.
         * @return void
         */
        base.move = function( position, rotate, callback )
        {
            var maxIndex = base.slidesNumber - 1;
            var rotated  = false;
            
            // if( base.animating ) {
            //     
            //     return;
            // }
            // 
            // base.animating = true;
            
            if( typeof base.options.onBeforeChange === 'function' ) {
                 
                base.options.onBeforeChange.call(
                    base,
                    base.currentPosition,
                    position,
                    rotated
                );
             }
            
            if( base.options.rotate && rotate ) {
                
                // Taken from AsSlider.js @ Antistatique.net
                if( rotate === 'next' && base.currentPosition === maxIndex && position === 0 ) {
                    
                    var $first = base.$slideInner.children( ':first' );
                    
                    base.$slideInner.css(
                        base.size,
                        ( base.innerSize + base.slideSize ) + 'px'
                    ).css(
                        base.margin,
                        - ( ( maxIndex - 1 ) * base.slideSize )
                    ).append(
                        $first
                    );
                    
                    rotated  = 'next';
                    position = maxIndex;
                    
                } else if( rotate === 'prev' && base.currentPosition === 0 && position === maxIndex ) {
                    
                    $last = base.$slideInner.children( ':last' );
                    
                    base.$slideInner.css(
                        base.size,
                        ( base.innerSize + this.slideSize ) + 'px'
                    ).css(
                        base.margin,
                        ( - base.slideSize ) + 'px'
                    ).prepend(
                        $last
                    );
                    
                    rotated  = 'prev';
                    position = 0;
                }
            }
            
            var options = {};
            
            options[ base.margin ] = ( - position ) * base.slideSize;
            
            base.$slideInner.stop().animate(
                options,
                base.options.easeTime,
                base.options.easeFunc,
                function()
                {
                    base.animating       = false;
                    var from             = base.currentPosition;
                    base.currentPosition = position;
                    
                    if( typeof callback === 'function' ) {
                        
                        callback.call(
                            base,
                            base.currentPosition,
                            from,
                            rotated
                        );
                     }
                    
                    if( typeof base.options.onAfterChange === 'function' ) {
                        
                        base.options.onAfterChange.call(
                            base,
                            base.currentPosition,
                            from,
                            rotated
                        );
                     }
                }
            );
            
            delete options;
        };
        
        base.getCurrent = function()
        {
            return base.$slides[ base.currentPosition ];
        };
        
        base.init();
        
        return base;
    };
    
    // Default options.
    $.nastyShow.defaultOptions = {
        mode           : 'horizontal',
        easeTime       : 700,
        easeFunc       : 'easeInOutExpo',
        rotate         : true,
        onBeforeChange : null,
        onAfterChange  : null,
        buttons        : null
    };
    
    // The plugin itself.
    $.fn.nastyShow = function( options )
    {
        var result = [];
        
        this.each( function( key )
        {
            result[ key ] = new $.nastyShow( this, options );
        } );
        
        return result;
    };
    
} )( jQuery );

// ]]>
