﻿( function ( $ ) {
    $.fn.carouselDefaults = {
        captionOpacity : 0.5,
        height : 400,
        thumbEndOpacity : 0.9,
        thumbStartOpacity : 0.4,
        thumbWidth : 80,
        width : 480
    };
    
    $.fn.carouselSettings = {};
    
    $.fn.carousel = function ( settings ) {
        /* Define the initial values for the options. */
        jQuery.extend( $.fn.carouselSettings, $.fn.carouselDefaults, settings );
        
        /* Merge the default Options with the Options parameter passed in. */
        
        
        return this.each( function () {
            var $container = $( this );
            
            var containerId = $( this ).attr( 'id' );
            
            /* If there is no ID on the container, then create one. */
            if ( containerId.length == 0 ) {
                containerId = new Date().getTime();
                $container.attr( 'id', containerId )
            }
            
            /* Get the number of images. */
            var ImageCount = $( '#' + containerId + ' > ul > li > img' ).length;
            
            /* Sanitize setting values. */
            $.fn.carouselSettings.height = parseInt( $.fn.carouselSettings.height, 10 );
            $.fn.carouselSettings.thumbWidth = parseInt( $.fn.carouselSettings.thumbWidth, 10 );
            $.fn.carouselSettings.width = parseInt( $.fn.carouselSettings.width, 10 );
            
            var boxModel = { 
                height : ( $.fn.carouselSettings.height - 6 ),
                width : ( $.fn.carouselSettings.width - 6 )
            };
            
            /* Add carousel class and set height / width of the containing <div> minus 6px for the border. */
            $container.addClass( 'jquery-carousel' ).height( boxModel.height ).width( boxModel.width );
            
            /* Create the basic thumbnail menu. */
            var $thumbnailMenu = $( '<div></div>' );
            
            $thumbnailMenu.addClass( 'jquery-carousel-thumbnails' );
            
            
            /**
             * Add the thumbnail container and set the width to match the overall carousel. Also, 116px is
             * removed from the overall width.  6px for the border of the carousel and 110px for the
             * navigation options.
             */
            $thumbnailMenu.append( '<div id="' + containerId + '-thumbnailContainer" class="thumbnail-container" style="width:' + ( $.fn.carouselSettings.width - 116 ) + 'px;">' );
            
            /* Prepend the Thumbnail Menu to come before the list of images. */
            $container.prepend( $thumbnailMenu );
            
            /* Append the captain to come after the list of images. */
            $container.append( '<div id="' + containerId + '-caption" class="jquery-carousel-caption">&nbsp;</div>' );
            $container.append( '<div id="' + containerId + '-captionText" class="jquery-carousel-captionText">No Caption.</div>' );
            
            $( '#' + containerId + '-caption' ).css( 'opacity', $.fn.carouselSettings.captionOpacity );
            
            /* Prepare the <ul> for the carousel functionality. */
            var imgContainerHeight = ( boxModel.height - 80 );
            $( '#' + containerId + ' > ul' ).height( imgContainerHeight ).width( boxModel.width * ImageCount );
            
            /* Set each image list item to be the same width and height. */
            $( '#' + containerId + ' > ul > li' ).height( imgContainerHeight ).width( boxModel.width );
            
            /* Create the scroll container for the thumbnails. */
            var $thumbnailScroll = $( '<div style="width:' + ( $.fn.carouselSettings.thumbWidth * ImageCount ) + 'px;"></div>' );
            
                        /* Add the buttons for navigation between thumbnails. */
            $thumbnailMenu.append( '<a id="' + containerId + '-left" href="#" class="options">&lt;</a>' );
            $thumbnailMenu.append( '<a id="' + containerId + '-right" href="#" class="options">&gt;</a>' );
            
            /**
             * For each <img> in the <ul>, determine the size and correct it to ensure it fits with the
             * dimensions of the of the <li>.  This will ensure that the picture is shrunk and centred
             * properly.
             */
            $( '#' + containerId + ' > ul > li > img' ).each( function () {
                var $img = $( this );
                
                /**
                 * Determine which dimensions to change and scale the image proportionally into the
                 * image container.
                 */
                var containerRatio = ( imgContainerHeight / boxModel.width );
                var imageRatio = ( $img.height() / $img.width() );
                
                /* Only scale the image if it's bigger than the container. */
                if ( $img.height() > imgContainerHeight || $img.width() > boxModel.width ) {
                    if ( imageRatio > containerRatio ) {
                        $img.height( imgContainerHeight );
                    }
                    else {
                        if ( $img.width() > boxModel.width ) {
                            $img.width( boxModel.width );
                        }
                        
                        /* Put a top margin on the image to center the image vertically. */
                        $img.css( 'marginTop', ( imgContainerHeight - $img.height() ) / 2 );
                    }
                }
                else {
                    $img.css( 'marginTop', ( imgContainerHeight - $img.height() ) / 2 );
                }
                
                /* Build thumbnail from image source. */
                var $thumbnailStub = $( '<a class="thumb">&nbsp;</a>' );
                
                $thumbnailStub.attr( 'href', $img.attr( 'src' ) );
                $thumbnailStub.css( 'background', 'url(' + $img.attr( 'src' ) + ') center center' ).css( 'opacity', $.fn.carouselSettings.thumbStartOpacity );
                
                /* Hook-up the fade in and fade out effect when the cursor hovers over. */
                $thumbnailStub.hover(
                    function () {
                        $( this ).animate( { opacity : $.fn.carouselSettings.thumbEndOpacity } );
                    },
                    function () {
                        if ( !$( this ).hasClass( 'active' ) ) {
                            $( this ).animate( { opacity : $.fn.carouselSettings.thumbStartOpacity } );
                        }
                    }
                );
                
                /* Hook-up the click event to display the full image. */
                $thumbnailStub.click( function ( e ) {
                    e.preventDefault();
                    e.stopPropagation();
                    this.blur();
                    
                    var $thisThumbnail = $( this );
                    
                    var carouselContainerId = $thisThumbnail.parents( 'div.jquery-carousel' ).attr( 'id' );
                    
                    /* Remove the previous active class and opacity. */
                    $( '#' + carouselContainerId + '-thumbnailContainer > div a.active' ).removeClass( 'active' ).css( 'opacity', $.fn.carouselSettings.thumbStartOpacity );
                    
                    /* Set the current option with the class and opacity. */
                    $thisThumbnail.addClass( 'active' ).css( 'opacity', $.fn.carouselSettings.thumbEndOpacity );
                    
                    /* Scroll thumbnail into view if it's partially visible. */
                    var marginPosition = $.fn.carouselThumbnailPosition( $( '#' + carouselContainerId + '-thumbnailContainer' ), $thisThumbnail );
                    
                    if ( marginPosition != 0 ) {
                        $( '#' + carouselContainerId + '-thumbnailContainer > div' ).animate( { marginLeft : '+=' + marginPosition } );
                    }
                    
                    /**
                     * Slide the image into view.
                     * NOTE: The each() method is being use to counteract a bug in jQuery's selector
                     * engine which affects IE6.  This means we can't access the image directly by using
                     * a selector.
                     * Ref : http://bugs.jquery.com/ticket/7128
                     * 
                     * Original Code : //var $imageEl = $( '#' + carouselContainerId + ' > ul img[src="' + $thisThumbnail.attr( 'href' ) + '"]' );
                     */
                    var $imageEl;
                    $( '#' + carouselContainerId + ' > ul img' ).each( function () {
                        if ( $( this ).attr( 'src' ) == $thisThumbnail.attr( 'href' ) ) {
                            $imageEl = $( this );
                            return;
                        }
                    } );
                    
                    $( '#' + carouselContainerId + ' > ul' ).animate( { marginLeft : "+=" + ( -$imageEl.parent().position().left ) } );
                    
                    $( '#' + carouselContainerId + '-captionText' ).text( $imageEl.attr( 'alt' ) );
                } );
                
                $thumbnailScroll.append( $thumbnailStub );
            } );
            
            /* Once complete, the thumbnail scroll container to the menu. */
            $( '#' + containerId + '-thumbnailContainer' ).append( $thumbnailScroll );
            
            /* Set the first thumbnail to be active and first image caption. */
            $( '#' + containerId + ' > .jquery-carousel-thumbnails > .thumbnail-container a:first-child' ).css( 'opacity', $.fn.carouselSettings.thumbEndOpacity ).addClass( 'active' );
            $( '#' + containerId + '-captionText' ).text( $( '#' + containerId + ' > ul > li:first-child > img' ).attr( 'alt' ) );
            
            /* Hook-up the click events for the left and right click. */
            $( '#' + containerId + '-left' ).click( function ( e ) {
                e.preventDefault();
                e.stopPropagation();
                this.blur();
                
                var carouselContainerId = $( this ).parents( 'div.jquery-carousel' ).attr( 'id' );
                $( '#' + carouselContainerId + '-thumbnailContainer > div a.active' ).prev().click();
            } );
            
            $( '#' + containerId + '-right' ).click( function ( e ) {
                e.preventDefault();
                e.stopPropagation();
                this.blur();
                
                var carouselContainerId = $( this ).parents( 'div.jquery-carousel' ).attr( 'id' );
                $( '#' + carouselContainerId + '-thumbnailContainer > div a.active' ).next().click();
            } );
        } );
    };
    
    /**
     * Return the difference of the top left or top right position depending if it is minus or positive.  We
     * only return the difference and return zero if the conditions are not true.
     * 
     * This code is used to determine if an element is located with the "viewable" area of an container
     * element.
     */
    $.fn.carouselThumbnailPosition = function ( $container, $element ) {
        var leftPositionDiff = ( $container.offset().left - $element.offset().left );
        var rightPositionDiff = ( $container.offset().left + $container.innerWidth() ) - ( $element.offset().left + $element.innerWidth() );
        
        if ( rightPositionDiff < 0 ) {
            return rightPositionDiff;
        }
        
        if ( leftPositionDiff > 0 ) {
            return leftPositionDiff;
        }
        
        return 0;
    };
} )( jQuery );
