/**
 * Carouselstronaut - It's out of this world!
 * 2011 Zachary Johnson www.zachstronaut.com
 * Dual MIT and GPL license, same as jQuery: http://jquery.org/license/
 *
 * -Move via click, touch, flick, swipe, prev/next arrows, or indicators
 */
function Carouselstronaut($container, options) {
    this.$container = $container;
    this.options = options || null;
    
    this.init();
}

Carouselstronaut.prototype = {
    init: function () {
        if (!this.$container || !this.$container.length || this.$container.hasClass('initialized')) {
            return;
        }

        var defaultOptions = {
            $prevnext: false,
            $indicator: false,
            marcopolo: false,
            forceLegacyAnimation: false
        };

        this.options = $.extend({}, defaultOptions, this.options);

        this.$prevnext = this.options.$prevnext;
        this.$indicator = this.options.$indicator;

        this.$mover = this.$container.find('ul.mover');
        this.$moverLis = this.$container.find('ul.mover > li');

        this.count = this.$moverLis.length;

        if (this.count <= 1) {
            return;
        }

        this.initItemPlaces();

        this.initIndicator();

        this.index = 0;
        this.offsetPercent = 0;

        this.animating = false;

        this.peekOffset = false;
    	this.prevPeekX = false;
    	this.peeking = false;

        this.setListeners();

        this.setClasses();

        this.$container.addClass('initialized');
    },

    initItemPlaces: function () {
        this.$moverLis.each(function (i) {
            $(this).css('left', (i * 100) + '%');
        });

        if (this.options.marcopolo) {
            var $prepend = this.$moverLis.last().clone().css('left', '-100%');
            var $append = this.$moverLis.first().clone().css('left', (this.count * 100) + '%');
            this.$mover.prepend($prepend);
            this.$mover.append($append);
            this.$moverLis = this.$container.find('ul.mover > li');
            // do not update this.count
        }
    },

    initIndicator: function () {
        if (this.$indicator && this.$indicator.length) {
            var i = this.count - this.$indicator.find('li').length;
            while (i--) {
                this.$indicator.append('<li><a href="#"></a></li>');
            }
        }
    },

    setClasses: function () {
        if (this.$indicator && this.$indicator.length) {
            this.$indicator.find('li').removeClass('current');
            this.$indicator.find('li').eq(this.index % this.count).addClass('current');
        }
    },

    afterChange: function () {
        if (this.options.marcopolo) {
            this.setIndex(this.index);
            this.offsetPercent = this.index * -100;
            this.peekOffset = 0;
            this.translatePeek();
        }

        this.setClasses();

        this.animating = false;
    },

    mouseToTouchEvent: function (e, handler) {
    	var evt = {changedTouches: [{identifier: 1, pageX: e.pageX, pageY: e.pageY}]};

    	handler.call(this, evt);
    },

    setListeners: function () {
        this.$container.find('img').mousemove(function (e) {e.preventDefault();}); // specifically for IE
        this.$moverLis.mousedown(function (e) {e.preventDefault();});

        this.$container.enableEventsTapFlick();

        var thisCarousel = this;

        if (TOUCHSUPPORT) {
            this.$container.get(0).addEventListener('touchmove', function (e) {e.preventDefault();}, false);

            this.$container.get(0).addEventListener('touchstart', function (e) {thisCarousel.startPeekHandler(e);}, false);
            document.body.addEventListener('touchmove', function (e) {thisCarousel.movePeekHandler(e);}, false);
            document.body.addEventListener('touchend', function (e) {thisCarousel.endPeekHandler(e);}, false);

        } else {
            this.$container.bind('mousedown', function (e) {thisCarousel.mouseToTouchEvent(e, thisCarousel.startPeekHandler);});
            $(document).bind('mousemove', function (e) {thisCarousel.mouseToTouchEvent(e, thisCarousel.movePeekHandler);});
            $(document).bind('mouseup', function (e) {thisCarousel.mouseToTouchEvent(e, thisCarousel.endPeekHandler);});
        }

        this.$container.bind('flick', function (e, direction) {
            if (direction == 'right') {
                thisCarousel.goPrev();
            } else if (direction == 'left') {
                thisCarousel.goNext();
            }
        });

        this.$container.bind('tap', function (e, data) {thisCarousel.tapHandler(data);});

        if (this.$prevnext) {
            this.$prevnext.find('li').first().click(function (e) {e.preventDefault(); thisCarousel.goPrev();});
            this.$prevnext.find('li').last().click(function (e) {e.preventDefault(); thisCarousel.goNext();});
        }

        if (this.$indicator) {
            this.$indicator.find('a').each(function (i) {
               $(this).click(function (e) {
                    e.preventDefault();

                    thisCarousel.$indicator.find('li').removeClass('current');
                    $(this).parent().addClass('current');

                    thisCarousel.goToIndex(i);
                }); 
            });
        }
    },

    tapHandler: function (data) {
        this.goNext();
    },

    startPeekHandler: function (e) {
        if (!this.animating && e.changedTouches.length > 0) {
            this.peeking = true;
            this.prevPeekX = e.changedTouches[0].pageX;
            this.peekOffset = 0;
        }
    },

    movePeekHandler: function (e) {
        if (this.peeking && !this.animating && e.changedTouches.length > 0) {
            this.peekOffset += (e.changedTouches[0].pageX - this.prevPeekX);
    		this.prevPeekX = e.changedTouches[0].pageX;

    		this.translatePeek();
        }
    },

    endPeekHandler: function (e) {
        if (this.peeking && !this.animating && e.changedTouches.length > 0) {
            var p = (this.peekOffset / this.$container.width()) * 100;
            if (p > 33) {
                this.goPrev();
            } else if (p < -33) {
                this.goNext();
            } else {
                this.goToIndex(this.index);
            }
        }

        this.peeking = false;
    },

    translatePeek: function () {
        var peek = (this.peekOffset / this.$container.width()) * 100;
        if (Math.abs(peek) > 99) {
            peek = 99 * (peek / Math.abs(peek));
        }

        if (this.options.forceLegacyAnimation) {
            this.$mover.css('left', (this.offsetPercent + peek) + '%');

        } else {
            this.$mover.translate3d((this.offsetPercent + peek) + '%', 0, 0);
        }
    },

    setIndex: function (newIndex) {
        newIndex = newIndex % this.count;
        if (newIndex < 0) {
            newIndex = newIndex + this.count;
        }

        this.index = newIndex;
    },

    goToIndex: function (index) {
        if (this.options.marcopolo) {
            this.index = index;

        } else {
            this.setIndex(index);
        }

        if ((this.offsetPercent + ((this.peekOffset / this.$container.width()) * 100)) == (this.index * -100)) {
            // transition won't fire callback if we are already at our destination value
            // and we don't want to set animating to true in that case
            return;
        }

        this.animating = true;

        this.offsetPercent = this.index * -100;

        var thisCarousel = this;

        if (this.options.forceLegacyAnimation) {
            this.$mover.stop().animate({left: thisCarousel.offsetPercent + '%'}, 700, function () {thisCarousel.afterChange();});

        } else {
            this.$mover.transition(
                function () {
                    $(this).addClass('snap');
                    $(this).translate3d(thisCarousel.offsetPercent + '%', 0, 0);
                },
                function () {
                    $(this).removeClass('snap');
                    thisCarousel.afterChange();
                },
                function () {
                    $(this).stop().animate({translateX3d: thisCarousel.offsetPercent + '%'}, 700, function () {thisCarousel.afterChange();});
                }
            );
        }
    },

    goNext: function () {
        if (!this.animating) {
            this.goToIndex(this.index + 1);
        }
    },

    goPrev: function () {
        if (!this.animating) {
            this.goToIndex(this.index - 1);
        }
    }
};



/**
 * JiantCarousel - No, I meant "JiantCarousel"
 * 2011 Zachary Johnson www.zachstronaut.com
 * Dual MIT and GPL license, same as jQuery: http://jquery.org/license/
 *
 * -Fullscreen fixed position carousel
 * -Supports being resized by changing window dimensions and all the
 *   resizing/repositioning is off-loaded to 100% CSS! No JS processing delay!
 * -Move only +1/-1 via click, touch, flick, swipe, or prev/next arrows
 * -Loops and repeats at the ends
 */
function JiantCarousel($container, options) {
    this.$container = $container;
    this.options = options;

    this.init();
}

$.extend(JiantCarousel.prototype, Carouselstronaut.prototype, {
    initItemPlaces: function () {
        // If there's only two li's, will need to duplicate the lis
        // to make smooth marco polo navigation
        if (this.count == 2) {
            var clone1 = this.$moverLis.eq(0).clone();
            var clone2 = this.$moverLis.eq(1).clone();
            this.$mover.append(clone1);
            this.$mover.append(clone2);
            this.$moverLis = this.$container.find('ul.mover > li');
            this.count = this.$moverLis.length;
        }
    },
    
    initIndicator: function  () {},
    
    setClasses: function () {
        var $current = this.$moverLis.eq(this.index % this.$moverLis.length);
        var $next = this.$moverLis.eq((this.index + 1) % this.$moverLis.length);
        var $prev = this.$moverLis.eq((this.index - 1) % this.$moverLis.length);
        
        if (this.options.forceLegacyAnimation) {
            $current.css('left', -this.offsetPercent + '%').addClass('inuse');
            $next.css('left', (-this.offsetPercent + 100) + '%').addClass('inuse');
            $prev.css('left', (-this.offsetPercent - 100) + '%').addClass('inuse');
            
        } else {
            $current.translate3d(-this.offsetPercent + '%', 0, 0).addClass('inuse');
            $next.translate3d((-this.offsetPercent + 100) + '%', 0, 0).addClass('inuse');
            $prev.translate3d((-this.offsetPercent - 100) + '%', 0, 0).addClass('inuse');
        }
    },
    
    setIndex: function(newIndex) {
        this.index = newIndex;
    },
    
    tapHandler: function (data) {
        if (data.pageX - this.$container.offset().left < this.$container.width() * 0.25) {
            this.goPrev();

        } else {
            this.goNext();
        }
    }
});



/**
 * AutoCarousel
 */
function AutoCarousel($container, options) {
    this.$container = $container;
    this.options = options;

    this.init();
}

$.extend(AutoCarousel.prototype, Carouselstronaut.prototype, {
    setListeners: function () {
        this.$container.find('img').mousemove(function (e) {e.preventDefault();}); // specifically for IE
        this.$moverLis.mousedown(function (e) {e.preventDefault();});
    }
});
