/*
jquery.w49.jqcarousel
Copyright Jasper Studios 2010
Author: Tom Walsham @tomwalsham
Note: For video content to work, wmode="opaque" must be specified,
or overlay video breaks the hidden areas;
For Youtube, append &amp;enablejsapi=1&amp;version=3 to the player location
to enable API access for 'pause on Playing'
*/
var jq_selected_idex = 1;

(function ($) {
    var carousel = function (caller, option) {

        var isInfinite = option;
        var autoPlay = isInfinite;
        var autoTimer = 5000; // milliseconds
        var timer;
        var playing; // State of current autoPlay
        var elementWidth;
        var elementCount;
        var index = 1; // Current index counter
        var orId = caller.attr('id'); // Calling object id
        var keyMap = 1; // Map arrow keys?

        initCarousel();  // Setup Carousel

        return createApi(); // Expose API for public js access

        function createApi() {
            return {
				// Declare exposed API functions here
                togglePlay: togglePlay,
                play: play,
                pause: pause,
                slide: slide,
                step: step,
                checkNext: checkNext
            }
        }

        function initCarousel() {
            elementCount = $('#' + orId + ' > li').size(); // Number of carousel elements
            elementWidth = $('#' + orId + ' li').outerWidth(); // Width of individual elements

            if (isInfinite) {
                $('#' + orId + ' li:first').before($('#' + orId + ' li:last')); // Shift last list to front to enable 'left' as first action
            }


            $('#' + orId).hover(function () { // Pause autoPlay on :hover
                pause();
            }, function () {
                if (autoPlay) {
                    play();
                }
            });

            if (keyMap == 1 && isInfinite) { // Bind keys for main carousel
                $(document).bind('keypress', function (e) {
                    if (e.keyCode == 37) {
                        slide('left');
                    } else if (e.keyCode == 39) {
                        slide('right');
                    }
                });

            }  

            if (autoPlay) {
                play();
            }


        } // End Carousel Initialise


        function togglePlay() {
            if (autoPlay) {
                autoPlay = false;
                pause();
            }
            else {
                autoPlay = true;
                play();
            }
        }

        function play() {
            //Start Autoplay
            timer = setInterval(slide, autoTimer);
            playing = true;
        }

        function pause() {
            //Pause Autoplay
            clearInterval(timer);
            playing = false;

        }

        function checkYoutube() {
            // Private function
            var emb = $('#' + orId + ' li:eq(1)').find('embed[src*=youtube]');

            if (emb.length) {
				// Youtube getPlayerState codes:
                // -1: Not started
                // 0: Finished
                // 1: Playing
                // 2: Paused;
                // 3: Buffering
                // 5: Cued
                if (jQuery.inArray(emb[0].getPlayerState(), [1, 3, 5]) >= 0) {
                    return (true);
                }
                else {
                    return (false);
                }
            }

        }


        function step(to) {  // Step carousel by X elements (for !isInfinite)
			if (isInfinite){return;}
            var maxOffset = elementCount * elementWidth;
            var currentOffset = parseInt($('#' + orId).css('margin-left'));
            var stepOffset = currentOffset + elementWidth * to;

            if (stepOffset <= 0 && stepOffset >= (-maxOffset)) { // Do not step if at limits  (for !isInfinite)
                $('#' + orId + ':not(:animated)').animate({
                    'margin-left': stepOffset
                }, 1000, function () {

                });
            }

        }

        function checkNext(to) {  // Check next 'step' if !isInfinite (for disable/enable stepper buttons)
			if (isInfinite){return;}
            var action = 'none';
            var maxOffset = -(elementCount * elementWidth);
            var currentOffset = parseInt($('#' + orId).css('margin-left'));
            var stepOffset = currentOffset + elementWidth * to * 2; // The value if the button was clicked again
            if (to > 0 && stepOffset > 0) {
                action = 'disable';
            }
            else if (to < 0 && stepOffset <= maxOffset) {
                action = 'disable';
            }
            return action;

        }
	 
        function slide(to, mode) { // to={left|right|signedint} mode={index|null}

            index = index % elementCount;
		    jq_selected_idex = index ;
            // Postpone autoplay on 'playing' youtube vid in main frame	
            if (checkYoutube()) {
                if (autoPlay) {
                    pause();
                    play(); // resets the setInterval	
                    return;
                }
            }


            var slidenum;

            if (mode == 'index') { // Scroll to specific index item
                var target = parseInt(to);
                clearInterval(timer);

                var diff = (target - index);

                if (diff == 0) {
                    slidenum = 0;
                }
                else if (diff == -1) {
                    slide('left');
                }
                else {
                    //rdiff = diff % elementCount;
                    // Modulus can return negative in js. Correct with following::
                    rdiff = (diff >= 0) ? (diff % elementCount) : ((diff % elementCount) + elementCount);

                    var left_indent = parseInt($('#' + orId).css('left')) - (rdiff * elementWidth);
                    slidenum = rdiff; // slidenum is iterated in the animate function
                }


            } // End mode == 'index'
            else if (to == 'left') {
                var left_indent = parseInt($('#' + orId).css('left')) + elementWidth;
            } else {
                var left_indent = parseInt($('#' + orId).css('left')) - elementWidth;
            }

            $('#' + orId + ':not(:animated)').animate({  // Do the slide animation
                'left': left_indent
            }, 1000, function () {  // Callback post-animation

                if (mode == 'index') {
                    for (i = 0; i < slidenum; i++) {
                        $('#' + orId + ' li:last').after($('#' + orId + ' li:first'));
                        index += 1;
						jq_selected_idex = index ;
                    }
                }
                else if (to == 'left' || slidenum == -1) {
                    $('#' + orId + ' li:first').before($('#' + orId + ' li:last'));
                    index -= 1;
					jq_selected_idex = index ;
                } else {
                    $('#' + orId + ' li:last').after($('#' + orId + ' li:first'));
                    index += 1;
					jq_selected_idex = index ;
                }

                // Fix the position post-animation & li swap
                $('#' + orId).css({
                    'left': -elementWidth
                });
                if (playing == 1) { // Reset timeout
                    clearInterval(timer);
                    timer = setInterval(slide, autoTimer);
                }
            });

        }

        function debug(dbvar) { // Use for visual debug output
			// Private function
            $('#debug').html(dbvar);
        }
    }

    $.fn.jqCarousel = function (option) {

        return new carousel(this, option);
    }

})(jQuery);
