/*
    jquery-puffslider.js
    jQuery Puff Slider plugin version 0.1 beta
    Copyright 2011 Sammy Nordström
    Requires jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
*/

(function(jQuery){
    jQuery.fn.reverse = function(fn) {       
        var i = this.length;
        while(i) {
            i--;
            fn.call(this[i], i, this[i])
        }
    };
})(jQuery);

(function(jQuery){
    
    jQuery.fn.puffSlider = function(options){
        
        // Merge defaults with possible overrides
        options = jQuery.extend(jQuery.fn.puffSlider.options, options);
        
        // Get sizes from selector
        options.scrollWrapper = jQuery(this);
        options.scrollableArea = jQuery("#scrollableArea");
        options.puffItemSize = jQuery("#scrollableArea .puffSliderItem").outerWidth();
        options.puffItemCount = jQuery("#scrollableArea .puffSliderItem").size();

        // Determine active puff and clone puffs on the right side
        jQuery('#scrollableArea .puffSliderItem').each(function(key, value) {
            if (jQuery(this).attr('id') == 'activePuff') {
                options.activePuffKey = key + options.puffItemCount;
                options.scrollableArea.append(jQuery(this)
                    .clone()
                    .removeAttr('id')
                    .find('#activePuffArrow').remove()
                    .end()
                );
            } else {
                jQuery(this).clone().appendTo(options.scrollableArea);
            }
            return true;
        });
        
        // Now clone puffs on the left
        var i = 0;
        jQuery('#scrollableArea .puffSliderItem').reverse(function(key, value) {
            if (i<options.puffItemCount) {
                jQuery(this).clone().prependTo(options.scrollableArea);
                i++;
                return true;
            } else {
                return false;
            }
        });
        
        // Calculate sizes and set up initial CSS
        options.puffsInWrapper = Math.ceil(options.scrollWrapper.outerWidth() / options.puffItemSize);
        options.leftMin = options.leftMax - (((options.puffItemCount * 3) - options.puffsInWrapper) * options.puffItemSize);
        options.scrollableArea.css("width", ((options.puffItemCount * options.puffItemSize) * 3));
        options.leftMargin = options.leftMax - (options.activePuffKey * options.puffItemSize);
        options.scrollWrapper.css("left", options.leftMargin);
        
        // Now export options as public variables
        jQuery.fn.puffSlider.options = options;
        
        // Assign click events
        jQuery.fn.puffSlider.bindPuffEvents();
        
        // Now add scroll function to the hover hotspots
        jQuery("#scrollingHotSpotLeft").hover(function() {
            if (!options.puffUnLocked) {
                jQuery("#scrollWrapper").data('loop', true).stop().puffSlider.scroll('left');
            } else {
                jQuery("#scrollWrapper").data('loop', false);
            }
        }, function(){
            jQuery("#scrollWrapper").data('started', false);
            jQuery("#scrollWrapper").data('loop', false);
            // Now our animation will stop after fully completing its last cycle
        });
        
        jQuery("#scrollingHotSpotRight").hover(function() {
            if (!options.puffUnLocked) {
                jQuery("#scrollWrapper").data('loop', true).stop().puffSlider.scroll('right');
            } else {
                jQuery("#scrollWrapper").data('loop', false);
            }
        }, function(){
            jQuery("#scrollWrapper").data('started', false);
            jQuery("#scrollWrapper").data('loop', false);
            // Now our animation will stop after fully completing its last cycle
        });
        
    };
    
    // Scroll function
    jQuery.fn.puffSlider.scroll = function(arg) {
        var options = jQuery.fn.puffSlider.options;
        var $this = options.scrollWrapper;
        var direction = '';
        var time = options.puffSlideTime;
        var easing = '';
        
        switch (arg) {
            case 'left':
            case 'right':
                direction = arg;
                easing = 'easeInOutQuart';
                time=time*2;
                break;
            default:
                arg = parseFloat(arg);
                if (isNaN(arg)) {
                    return false;
                } else {
                    // Assume numeric arg is number of puffs to scroll,
                    // negative for left and positive for right
                    arg = Math.round(arg);
                    if (arg != 0) {
                        if (arg > 0) {
                            direction = 'right';
                            arg--;
                        } else if (arg < 0) {
                            direction = 'left';
                            arg++;
                        }
                        if (arg == 0) {
                            if ($this.data('started') == true) {
                                $this.data('started', false);
                                easing = 'easeOutBack';
                                time = time;
                            } else {
                                easing = 'easeInOutQuart';
                                time = time*2;
                            }
                        } else {
                            if ($this.data('started') == true) {
                                easing = 'linear';
                                time = Math.round(time/($this.data('steps')+1));
                            } else {
                                $this.data('started', true);
                                $this.data('steps', arg);
                                easing = 'easeInQuart';
                                time = time;
                            }
                        }
                        $this.data('loop', true);
                    } else {
                        $this.data('loop', false);
                    }
                }
                break;
        }
        
        if( $this.data('loop') == true) {       
                if (direction == 'right') {
                    options.leftMargin = options.leftMargin - options.puffItemSize;
                }
                if (direction == 'left') {
                    options.leftMargin = options.leftMargin + options.puffItemSize;
                }
                $this.puffSlider.unLockPuff(function() {
                    $this.animate( {left: options.leftMargin}, time, easing, function() {
                        if (direction == 'right') {
                            jQuery('#scrollableArea').append(jQuery('#scrollableArea .puffSliderItem').first());
                            options.leftMargin = options.leftMargin + options.puffItemSize;
                            options.scrollWrapper.css("left", options.leftMargin);
                        }
                        if (direction == 'left') {
                            jQuery('#scrollableArea').prepend(jQuery('#scrollableArea .puffSliderItem').last());
                            options.leftMargin = options.leftMargin - options.puffItemSize;
                            options.scrollWrapper.css("left", options.leftMargin);
                        }
                        if ($this.data('loop') == true) {
                            $this.puffSlider.scroll(arg);
                        } else {
                            $this.puffSlider.activatePuff(options.activePuffKey);
                            $this.puffSlider.lockPuff();
                            $this.puffSlider.bindPuffEvents();
                        }
                    });
                });   
        } else {
            $this.data('started', false);
            $this.puffSlider.activatePuff(options.activePuffKey);
            $this.puffSlider.lockPuff();
            $this.puffSlider.bindPuffEvents();
        }
        
        return $this; // Don't break the chain
    };
    
    jQuery.fn.puffSlider.bindPuffEvents = function() {
        var options = jQuery.fn.puffSlider.options;
        jQuery("#scrollableArea .puffSliderItem").each(function(key, value) {
            jQuery(this).unbind('click');
            if (key != options.activePuffKey) {
                jQuery(this).click(function() {
                    var steps = key - options.activePuffKey;
                    jQuery.fn.puffSlider.scroll(steps);
                });
            } else if (options.hasPuffPosts) {
                if (jQuery(this).find(".puffPost")) {
                    var activePuff = jQuery(this).find(".puffPost");
                    jQuery(options.puffPostElement).fadeTo(options.puffPostFadeTime, 0, function() {
                        jQuery(options.puffPostElement).html(activePuff.html());
                        jQuery(options.puffPostElement).fadeTo(options.puffPostFadeTime, 1);
                    });
                }
            }
            return true;
        });
    }
    
    jQuery.fn.puffSlider.activatePuff = function(newKey) {
        var options = jQuery.fn.puffSlider.options;
        jQuery('#scrollableArea .puffSliderItem').each(function(key, value) {
            if (key == newKey) {
                jQuery(this).attr('id', 'activePuff');
                jQuery(this).append(jQuery('#scrollableArea .puffSliderItem #activePuffArrow'));
            } else {
                jQuery(this).removeAttr('id');
            }
        });
        options.activePuffKey = newKey;
    };
    
    jQuery.fn.puffSlider.unLockPuff = function(callback) {
        var options = jQuery.fn.puffSlider.options;
        if (!options.puffUnLocked) {
            options.puffUnLocked = true;
            if (options.hasPuffPosts) {
                jQuery(options.puffPostElement).fadeTo(options.puffPostFadeTime, 0);
            }
            if (options.animateArrow) {
                return jQuery('#scrollableArea .puffSliderItem #activePuffArrow').animate(options.animateArrowArg, options.animateArrowTime, callback);
            }
        }
        if (typeof callback == 'function') {
            return callback();
        } else {
            return callback;
        }
    };
    
    jQuery.fn.puffSlider.lockPuff = function(callback) {
        var options = jQuery.fn.puffSlider.options;
        if (options.puffUnLocked) {
            options.puffUnLocked = false;
            if (options.animateArrow) {
                return jQuery('#scrollableArea .puffSliderItem #activePuffArrow').animate(options.resetArrowArg, options.animateArrowTime, callback);
            }
        }
        if (typeof callback == 'function') {
            return callback();
        } else {
            return callback;
        }
    };
    
    jQuery.fn.puffSlider.options = {
        
        // Set animation time per puff (ms)
        puffSlideTime:  320,
        
        // Set max left position
        leftMax:        0,
        
        // Animate arrow effect
        animateArrow:      true,
        
        // Arrow animation argument
        animateArrowArg:        {top: '-9px'},
        
        // Arrow animation argument
        resetArrowArg:        {top: '0px'},
        
        // Arrow animation time (ms)
        animateArrowTime:       320,
        
        hasPuffPosts: true,
        
        puffPostElement: '#main .contentWrapper .postContainer',
        
        puffPostFadeTime:   320
    
    };
    
})(jQuery);
