(function($) {
    $.fn.dsSlideShow = function( method )
    {
        // method calling logic
        if ( methods[method] )
            return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ) );
        else if ( typeof method === 'object' || ! method )
            return methods.init.apply( this, arguments );
        else
            $.error( 'Method ' +  method + ' does not exist' );
    };
    
    // default state variables 
    var defaults = {
        timer: null
    }
    
    // overridable options
    var defaultOptions = {
        autoPlay: false,
        transitionLength: 2000,
        slideLength: 5000        
    }
    
    // public methods
    var methods = {
        // initilization
        init: function ( userOptions )
        {
            return this.each(function()
            {
                $element = $(this);
                $element.data.dsSlideShow = $.extend({}, defaultOptions, userOptions, defaults);
                settings = $element.data.dsSlideShow;
                
                // container css
                $element.css({
                    'position': 'relative'
                });
                
                // slide css
                $element.children('img').css({
                    'position': 'absolute',
                    'top': 0,
                    'left': 0,
                    'opacity': 0,
                    'display': 'none'
                });

                // active slide css
                $element.children('img.active').css({
                    'opacity': 1,
                    'display': 'block'
                });
                
                // warn the developer if the transition is longer than the slide will be displaying
                if ( settings.transitionLength > settings.slideLength )
                {
                    alert('dsSlideShow Erorr: The transition length cannot be longer than the slide length');
                    return this;
                }
                
                // create the control box
                $controlBox = $('<div class="dsSlideShow_controls"></div>');
                
                // create the previous button
                $prevButton = $('<span class="dsSlideShow_prev">Prev</span>').click(function()
                {
                    $element.dsSlideShow('prev');
                    $element.dsSlideShow('stop');
                    //$element.dsSlideShow('play');
                });
                
                // create the play button
                $playButton = $('<span class="dsSlideShow_play">Play</span>').click(function()
                {
                    $element.dsSlideShow('play');
                });
                
                // create the stop button
                $stopButton = $('<span class="dsSlideShow_stop">Stop</span>').click(function()
                {
                    $element.dsSlideShow('stop');
                });
                
                // create the next button
                $nextButton = $('<span class="dsSlideShow_next">Next</span>').click(function()
                {
                    $element.dsSlideShow('next');
                    $element.dsSlideShow('stop');
                    //$element.dsSlideShow('play');
                });
                
                // add the buttons to the control box
                $controlBox
                    .append($prevButton)
                    .append($playButton)
                    .append($stopButton)
                    .append($nextButton);
                
                // style the control box
                $controlBox.css({
                    'text-align': 'center',
                    'display': 'none',
                    'opacity': 0,
                    'z-index': 10,
                    'width': '200px',
                    'height': '40px',
                    'position': 'absolute',
                    'bottom': '15px',
                    'left': ( $element.width() / 2 ) - 100 + 'px',
                    'color': '#fff'
                });
                
                // style the control box buttons
                $controlBox.children('span').css({
                    'cursor': 'pointer',
                    'padding': '7px',
                    'background-color': 'rgba(0,0,0,0.3)'
                });
                
                // add text hover to control box buttons
                $controlBox.children('span').hover(function()
                {
                    $(this).css('color', 'yellow');
                },
                function ()
                {
                    $(this).css('color', '');
                });
                
                // show control box when hovered 
                $element
                    .mouseenter(function()
                    {
                        $controlBox
                            .stop()
                            .show()
                            .animate({'opacity': 1.0}, 250);
                    })
                    .mouseleave(function()
                    {
                        $controlBox
                            .stop()
                            .animate({'opacity': 0}, 250, function()
                            {
                                $controlBox.hide();
                            });
                    });
                
                // add the control box to the slideshow
                $element.append($controlBox);
                
                // prevent text highlighting in the control box
                $controlBox.disableSelection();
                
                // auto play if desired
                if ( userOptions.autoPlay == true )
                    $element.dsSlideShow('play');
            });
        },
        // next slide
        next: function ()
        {
            return this.each(function()
            {
                $element = $(this);
                $active = $element.children('img.active');
                $next = $active.next('img').length ? $active.next('img') : $element.children('img:first');

                changeSlide($element, $active, $next);
            });
        },
        // previous slide
        prev: function ()
        {
            return this.each(function()
            {
                $element = $(this);
                $active = $element.children('img.active');
                $next = $active.prev('img').length ? $active.prev('img') : $element.children('img:last');

                changeSlide($element, $active, $next);
            });
        },
        // play slideshow
        play: function ()
        {
            return this.each(function()
            {
                $element = $(this);
                
                $element.find('.dsSlideShow_play').hide();
                $element.find('.dsSlideShow_stop').show();
                
                $element.data.dsSlideShow.timer = setInterval(function()
                {
                    $element.dsSlideShow('next');
                },
                $element.data.dsSlideShow.slideLength);
            });
        },
        // stop slideshow
        stop: function ()
        {
            return this.each(function()
            {
                $element = $(this);
                
                $element.find('.dsSlideShow_stop').hide();
                $element.find('.dsSlideShow_play').show();
                
                clearInterval($element.data.dsSlideShow.timer);
            });
        }
    };
    
    // private methods
    function changeSlide($element, $active, $next)
    {
        $element.children('img').not('.active').stop(true,true);
        
        // lower the current image
        $active
            .stop(true, true)
            .removeClass('active')
            .animate({'opacity': 0.0}, $element.data.dsSlideShow.transitionLength, function()
            {
                $active.hide()
            });
        
        // raise and display the next (transparent) image
        $next
            .stop(true, true)
            .addClass('active')
            .show()
            .animate({'opacity': 1.0}, $element.data.dsSlideShow.transitionLength);
    } 
})( jQuery );
