/*
 * jSlider
 * 
 * Author: Joshua Gildart
 * Last Updated: May 2nd 2011
 */

(function () {
    var JSlider = function (container, options) {
        // defaults slider settings are below
        var settings = $.extend({}, $.fn.jSlider.defaults, options);
        // 
        var vars = {
            currentContentIndex: 0,
            currentContent: '',
            totalContentLength: 0,
            containerWidth: 0,
            containerHeight: 0,
            currentlyAnimated: false,
            animationInterval: undefined,
            innerContainer: undefined
        };

        /**
         * Animation Options are: fade, blip, slideOverLeft, slideOverLeft, slideLeft, carousel
         */
        // set up variables
        var container = $(container);
        container.css({
            position: 'relative',
            overflow: 'hidden'
        });
        var tempContent = container.find('.slide');
        vars.totalContentLength = tempContent.length;
        
        $(window).load(function(){
        
            // itterate over the found slide content
            tempContent.each(function(i){
                currentObj = $(this);
                
                contentWidth = currentObj.width();
                contentHeight = currentObj.height();				
                
                if(contentWidth == 0) contentWidth = currentObj.attr('width');
                if(contentHeight == 0) contentHeight = currentObj.attr('height');
            
                if(contentWidth > vars.containerWidth) vars.containerWidth = contentWidth;
                if(contentHeight > vars.containerHeight) vars.containerHeight = contentHeight;
                
                // if the content is not a div, wrap the content in a div
                if(!currentObj.is('div')) {
                    newContent = $('<div class="jSlideContent" />');
                    newContent.append(currentObj.clone());
                } else {
                    newContent = currentObj.addClass('jSlideContent').clone();
                }
                
                container.append(newContent);
                currentObj.remove();
            });
            // convert JS array into a jQuery object
            var content = container.find('.jSlideContent');
           
            // reposition the content in the container based on the animation
            if(settings.animation == 'slideOverLeft' || settings.animation == 'slideOverRight') {
                content.each(function(i) {
                    currentObj = $(this);
                    currentObj.css({
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        zIndex: 10
                    });
                    
                    if(i) currentObj.css('left', vars.containerWidth * (settings.animation == 'slideOverRight' ? -1 : 1));
                });
            } else if(settings.animation == 'fade' || settings.animation == 'blip') {
                content.each(function(i) {
                    currentObj = $(this);
                    currentObj.css({
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        zIndex: 10,
                        display: i ? 'none' : 'block' // first image gets displayed, rest are hidden
                    });
                });
                // if this is a blip animation, limit the animation speed to 500 for effect
                if(settings.animation == 'blip' && settings.animationSpeed > 500) {
                    settings.animationSpeed = 500;
                }
            } else if(settings.animation == 'slideLeft') {
                content.each(function(i) {
                    currentObj = $(this);
                    currentObj.css({
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        zIndex: 10
                    });
                    
                    if(i) currentObj.css('left', vars.containerWidth * i * (settings.animation == 'slideOverRight' ? -1 : 1));
                });
                
                vars.innerContent = $('<div style="position:absolute" />').append(content);
                container.append(vars.innerContent);
            } else if(settings.animation == 'carousel') {
                content.each(function(i) {
                    currentObj = $(this);
                    currentObj.css({
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        zIndex: 10
                    });
                    
                    if(i) currentObj.css('left', vars.containerWidth);
                });
            }

            // update container
            container.css({
                width: vars.containerWidth,
                height: vars.containerHeight,
                '-webkit-user-select': 'none',
                '-khtml-user-select': 'none',
                '-moz-user-select': 'none',
                '-o-user-select': 'none',
                'user-select': 'none'
            });
            
            content.css({
                width: vars.containerWidth, 
                height: vars.containerHeight
            });
            
            // start effects
            if(settings.autoStart) {
                vars.animationInterval = setInterval(function() {
                    transition('forward');
                }, settings.speed);
            }
            
            // create navigation elements
            if(settings.navigationEnabled) {
                // left and right navigation
                if(settings.navigationType == 'leftright') {
                    var navLeft = $('<div id="jSliderNav-left" class="jSliderNav" style="position:absolute;z-index:12;cursor:pointer" />');
                    var navRight = $('<div id="jSliderNav-right" class="jSliderNav" style="position:absolute;z-index:12;cursor:pointer" />');
                    container.append(navLeft).append(navRight);

                    navLeft.css({
                        width: Math.floor(vars.containerWidth / 4.1),
                        height: vars.containerHeight,
                        top: 0,
                        left: 0
                    }).mouseenter(function() {
                        $(this).addClass('jSliderNavLeftActive');
                    }).mouseleave(function() {
                        $(this).removeClass('jSliderNavLeftActive');
                    }).click(function() {
                        if(!vars.currentlyAnimated) {
                            transition('backward');
                            if(settings.autoStart) {
                                resetAnimationInterval();
                            }
                        }
                    });

                    navRight.css({
                        width: Math.floor(vars.containerWidth / 4.1),
                        height: vars.containerHeight,
                        top: 0,
                        right: 0
                    }).mouseenter(function() {
                        $(this).addClass('jSliderNavRightActive');
                    }).mouseleave(function() {
                        $(this).removeClass('jSliderNavRightActive');
                    }).click(function() {
                        if(!vars.currentlyAnimated) {
                            transition('forward');
                            if(settings.autoStart) {
                                resetAnimationInterval();
                            }
                        }
                    });
                }
                // numbered (1, 2, 3) navigation
                if(settings.navigationType == 'numbered') {
                    var navContainer = $('<div id="jSliderNav-numbered" style="position:absolute;z-index:13;bottom:0;" />');
                    for(var i = 0; i < vars.totalContentLength; i++) {
                        var number = $('<div class="jSliderNav-number ' + (i == 0 ? 'jSliderNumberActive' : '') + '" index="' + i + '">' + (i + 1) + '</div>');
                        number.css({
                            '-webkit-user-select': 'none',
                            '-khtml-user-select': 'none',
                            '-moz-user-select': 'none',
                            '-o-user-select': 'none',
                            'user-select': 'none'
                        }).click(function(){
                            if(!vars.currentlyAnimated) {
                                transition(null, $(this).attr('index'));
                                if(settings.autoStart) {
                                    resetAnimationInterval();
                                }
                            }
                        });
                        navContainer.append(number);
                    }
                    
                    container.append(navContainer);
                }
                // textual previousnext navigation
                if(settings.navigationType == 'previousnext') {
                    var navContainer = $('<div id="jSliderNav-previousnext" style="position:absolute;z-index:12;" />');
                    var navPrevious = $('<div id="jSliderNav-previous">previous</div>');
                    var navNext = $('<div id="jSliderNav-next">next</div>');
                    navContainer.append(navPrevious).append(navNext);
                    container.append(navContainer);
                    // adjust the containers
                    navContainer.width(container.width()).css({
                        top: container.height()
                    });
                    container.height(container.height() + navContainer.height());
                    // adjust the navigation elements and attach event handlers
                    navPrevious.css({
                        float: 'left',
                        paddingLeft: '15px',
                        cursor: 'pointer',
                        '-webkit-user-select': 'none',
                        '-khtml-user-select': 'none',
                        '-moz-user-select': 'none',
                        '-o-user-select': 'none',
                        'user-select': 'none'
                    }).click(function() {
                        if(!vars.currentlyAnimated) {
                            transition('backward');
                            if(settings.autoStart) {
                                resetAnimationInterval();
                            }
                        }
                    });
                    
                    navNext.css({
                        float: 'right',
                        paddingRight: '15px',
                        cursor: 'pointer',
                        '-webkit-user-select': 'none',
                        '-khtml-user-select': 'none',
                        '-moz-user-select': 'none',
                        '-o-user-select': 'none',
                        'user-select': 'none'
                    }).click(function() {
                        if(!vars.currentlyAnimated) {
                            transition('forward');
                            if(settings.autoStart) {
                                resetAnimationInterval();
                            }
                        }
                    });
                }
            }
            
            // set current image
            vars.currentContent = $(content[vars.currentContentIndex]);
            
            var resetAnimationInterval = function () {
                clearInterval(vars.animationInterval);
                vars.animationInterval = setInterval(function() {
                    transition('forward');
                }, settings.speed);
            } 
            
            /**
             * The transition function is where the effects take place. A direction of forward or backward
             * is passed in order to determine whether to increment or decrement the image index. ifno
             * direction is specified, forward is assumed.
             */
            var transition = function (to, index) {
                var nextIndex = 
                    index ? 
                    parseInt(index) : (
                        to == 'backward' ? 
                        (vars.currentContentIndex == 0 ? vars.totalContentLength - 1 : vars.currentContentIndex - 1) : 
                        (vars.currentContentIndex == vars.totalContentLength - 1 ? 0 : vars.currentContentIndex + 1)
                    );
                
                if(settings.animation == 'fade') {
                    vars.currentContent.fadeOut(settings.animationSpeed);
                    vars.currentContentIndex = nextIndex;
                    vars.currentContent = $(content[vars.currentContentIndex]);
                    vars.currentlyAnimated = true;
                    vars.currentContent.fadeIn(settings.animationSpeed, function(){
                        vars.currentlyAnimated = false;
                    });
                }
                
                if(settings.animation == 'blip') {
                    vars.currentContent.hide();
                    vars.currentContentIndex = nextIndex;
                    vars.currentContent = $(content[vars.currentContentIndex]);
                    vars.currentlyAnimated = true;
                    vars.currentContent.fadeIn(settings.animationSpeed, function(){
                        vars.currentlyAnimated = false;
                    });
                }

                if(settings.animation == 'slideOverLeft' || settings.animation == 'slideOverRight') {
                    lastContent = vars.currentContent;
                
                    vars.currentContent.css('z-index', 10);
                    vars.currentContentIndex = nextIndex;
                    vars.currentContent = $(content[vars.currentContentIndex]).css('z-index', 11);
                    vars.currentlyAnimated = true;
                    vars.currentContent.animate({
                        left: 0
                    }, settings.animationSpeed, function () {
                        lastContent.css({
                            left: vars.containerWidth * (settings.animation == 'slideOverRight' ? -1 : 1)
                        });
                        
                        vars.currentlyAnimated = false;
                    });
                }
                
                if(settings.animation == 'slideLeft') {
                    vars.currentContentIndex = nextIndex;
                    vars.currentlyAnimated = true;
                    vars.innerContent.animate({
                        left: vars.currentContentIndex * vars.containerWidth * -1
                    }, settings.animationSpeed, function () {
                        vars.currentlyAnimated = false;
                    });
                    $('.jSliderNav-number').removeClass('jSliderNumberActive');
                    $('.jSliderNav-number[index=' + nextIndex + ']').addClass('jSliderNumberActive');
                }
                
                if(settings.animation == 'carousel') {
                    // setup the content variables
                    lastContent = vars.currentContent;
                    vars.currentContentIndex = nextIndex;
                    vars.currentContent = $(content[vars.currentContentIndex]);
                    
                    // position according to direction
                    if(to == 'backward') {
                        vars.currentContent.css('left', vars.containerWidth * -1);
                    }
                    
                    vars.currentlyAnimated = true;
                    
                    lastContent.animate({left: to == 'backward' ? vars.containerWidth : vars.containerWidth * -1}, settings.animationSpeed);
                    
                    vars.currentContent.animate({
                        left: 0
                    }, settings.animationSpeed, function () {
                        vars.currentlyAnimated = false;
                        lastContent.css('left', vars.containerWidth);
                    });
                    
                    $('.jSliderNav-number').removeClass('jSliderNumberActive');
                    $('.jSliderNav-number[index=' + nextIndex + ']').addClass('jSliderNumberActive');
                }
            }
        }); // end window load
    };

    /**
     * This is the constructor of the slider.
     */
    $.fn.jSlider = function (options) {
        return this.each(function () {
            var element = $(this);
            // return early ifthis element already has a plugin instance
            if(element.data('jslider')) return;
            // pass options to plugin constructor
            var jslider = new JSlider(element, options);
            // store plugin object in this element's data
            element.data('jslider', jslider);
        });
    };

    /**
     * These are the default options ifnothing overloaded in the constructor.
     */
    $.fn.jSlider.defaults = {
        speed: 7000,
        animationSpeed: 2500,
        animation: 'fade',
        autoStart: true,
        navigationEnabled: false,
        navigationType: 'leftright',
        containerWidth: null,
        containerHeight: null
    };
})(jQuery);
