/**
 * CJ Slideshow - simple fading slideshow with captions
 *
 * Copyright (c) 2011 Creative Jar
 *
 * Version 0.2
 *
 */

(function ($) {
    $.fn.cjSlideshow = function (options) {
        options = $.extend({
            items: "figure", // Item's container
            caption: null, //  Items
            speed: "1600", // Global animation speed
            autoPlaySpeed: null, // Auto play speed
            pagerClass: null, // Paging CSS class
            pagerCurrentClass: "current", // Current CSS class for paging
            btnPrevClass: null, // Previous button CSS class
            btnNextClass: null, // Next button CSS class
            btnDisabledClass: "disabled", // CSS class for when prev/next buttons are disabled
            btnControlClass: null // Play/pause button CSS class
        }, options || {});

        return this.each(function () {
            var oElement = $(this), // Set main element
            oItems = $(options.items, oElement), // Set items collection within element
            oItemsLength = $(oItems).size(), // Get number of items
            oCurrent = 1, // Set current item to 1
            oTransitioning = false, // Set slideshow currently transitioning to false, will be used later to prevent queuing
            oHoverPause = false, // Set hover pause to false
            oControlPause = false, // Set play/pause control pause to false
            oWindowPause = false; // Set window pause to false

            oItems.css({ "position": "absolute", "top": "0", "left": "0" }); // Set items CSS

            setStackingOrder(); // Set initial stacking order

            if (options.autoPlaySpeed) { // Check if auto play speed has been defined
                var autoPlay = setInterval(function () { // Define auto play function
                    if (oHoverPause == false && oControlPause == false && oWindowPause == false) { // Check if hover or control pause is false
                        runTransition(); // Run transition
                    }
                }, options.autoPlaySpeed);

                $(oElement).hover(function () { // On element hover
                    oHoverPause = true; // Set hover pause to true
                }, function () { // On element mouse out
                    oHoverPause = false; // Set hover pause to false
                });

                if (window.addEventListener) {
                    window.addEventListener('focus', function () { // On window focus
                        oWindowPause = false; // Set window pause to false
                    }, false);
                    window.addEventListener('blur', function () { // On window focus
                        oWindowPause = true; // Set window pause to false
                    }, false);
                } else if (window.attachEvent) {
                    window.attachEvent('focus', function () { // On window focus
                        oWindowPause = false; // Set window pause to false
                    });
                    window.attachEvent('blur', function () { // On window focus
                        oWindowPause = true; // Set window pause to false
                    });
                }

            }

            if (options.btnControlClass && options.autoPlaySpeed) { // Check if play/pause button class exists and auto play speed has been defined
                $(oElement).append("<a class='" + options.btnControlClass + "'>Pause</a>"); // Append control
                $("a." + options.btnControlClass, oElement).click(function () { // Control click event
                    if ($(this).html() == "Pause") { // If this is currently paused
                        $(this).html("Play").addClass("paused"); // Set to pause
                        oControlPause = true; // Set control pause to true
                    }
                    else if ($(this).html() == "Play") { // If this is currently paused
                        $(this).html("Pause").removeClass("paused"); // Set to play
                        oControlPause = false; // Set control pause to false
                    }
                });
            }

            if (options.btnNextClass) { // Check if next button class exists
                if (oCurrent == oItemsLength) { // Check if at end
                    $(oElement).append("<a class='" + options.btnNextClass + " " + options.btnDisabledClass + "'>Next</a>"); // Append next button with disabled CSS class
                }
                else {
                    $(oElement).append("<a class='" + options.btnNextClass + "'>Next</a>"); // Append next button
                }
                $("a." + options.btnNextClass, oElement).fadeIn(options.speed).click(function () { // Fade next button in and set click function
                    if (!$(this).hasClass(options.btnDisabledClass)) { // Check if disabled
                        setStackingOrder(oCurrent + 1);
                    }
                });
            }

            if (options.btnPrevClass) { // Check if previous button class exists
                if (oCurrent == "1" && !options.loop) { // Check if at beginning
                    $(oElement).prepend("<a class='" + options.btnPrevClass + " " + options.btnDisabledClass + "'>Previous</a>"); // Append previous button with disabled CSS class
                }
                else {
                    $(oElement).prepend("<a class='" + options.btnPrevClass + "'>Previous</a>"); // Append previous button
                }
                $("a." + options.btnPrevClass, oElement).fadeIn(options.speed).click(function () { // Fade previous button in and set click function
                    if (!$(this).hasClass(options.btnDisabledClass)) { // Check if disabled
                        setStackingOrder(oCurrent - 1);
                    }
                });
            }

            if (options.pagerClass) { // Check if pager class exists
                $(oElement).append("<ul class='" + options.pagerClass + "'></ul>"); // Append pager container to after element
                oSlide = 1; // Set slide to 1
                $(options.items, oElement).each(function () { // For each item
                    if ($(options.items + ":nth-of-type(" + oSlide + ")", oElement).attr('data-title')) { // If this slide has a title
                        oSlideName = $(options.items + ":nth-of-type(" + oSlide + ")", oElement).attr('data-title'); // Get title
                    }
                    else {
                        oSlideName = oSlide; // Set title to slide number
                    }

                    if (oSlide == oCurrent) { // Check if slide is current
                        $("ul." + options.pagerClass, oElement).append("<li><a href='#" + oSlide + "' class='" + options.pagerCurrentClass + "'>" + oSlideName + "</a></li>"); // Append item to pager with current CSS class
                    } else {
                        $("ul." + options.pagerClass, oElement).append("<li><a href='#" + oSlide + "'>" + oSlideName + "</a></li>"); // Append item to pager
                    }
                    oSlide++; // Increase slide by 1
                });

                $("ul." + options.pagerClass + " li a", oElement).click(function () { // Pager click event
                    if (!$(this).hasClass(options.pagerCurrentClass)) { // Check if item does not have CSS class of current
                        var oTargetItem = $(this).attr("href").split("#"); // Get target item
                        setStackingOrder(oTargetItem[1]); // Set stacking order & call transition
                    }
                    return false;
                });
            }

            function setStackingOrder(jumpPrep) {
                var count = oItemsLength; // Count number of items
                if (!jumpPrep) { // If not jump
                    jumpPrep = 0;
                }
                oItems.each(function () { // Each item
                    if (jumpPrep > 0 && $(this).is(":nth-of-type(" + jumpPrep + ")")) { // If jumpPrep is bigger than 0 and this slide is the jumpTo slide
                        $(this).css({ "z-index": (oItemsLength - 1) }); // Set slide to 1 below top
                    }
                    else if ($(this).is(":nth-of-type(" + oCurrent + ")")) { // If this is the current slide
                        $(this).css({ "z-index": oItemsLength }); // Set slide to top
                    }
                    else if (oCurrent < oItemsLength && jumpPrep == 0 && $(this).is(":nth-of-type(" + (oCurrent + 1) + ")")) { // If current slide is not last, jumpPrep is 0 and this slide is the next slide to current
                        $(this).css({ "z-index": (oItemsLength - 1) }).find(options.caption, oElement).hide(); // Set slide to 1 below top and hide caption
                    }
                    else if (oCurrent == oItemsLength && jumpPrep == 0 && $(this).is(":first-of-type")) { // If current slide is last slide, jumpPrep is 0 and this slide is first slide
                        $(this).css({ "z-index": (oItemsLength - 1) }).find(options.caption, oElement).hide(); // Set slide to 1 below top and hide caption
                    }
                    else {
                        $(this).css({ "z-index": "1" }).find(options.caption, oElement).hide(); // Set slide to bottom and hide caption
                    }
                    $(this).css({ "display": "block" }); // Set item to show
                    if (--count == 1 && jumpPrep > 0) { // If last item through loop and jumpPrep is bigger than 0
                        runTransition(jumpPrep); // Run transition
                    }
                });
            }

            function runTransition(jump, callback) {
                if (!oTransitioning) { // If not transitioning
                    oTargetItem = $(options.items + ":nth-of-type(" + oCurrent + ")", oElement); // Set current item
                    oTransitioning = true; // Set transitioning to true
                    $(options.items + ":nth-of-type(" + oCurrent + ")", oElement).stop(true).fadeOut(options.speed, function () { // Fade out current its,
                        if (jump) { // If jump is defind
                            if (options.caption) { // Check if captions is defined
                                $(options.items + ":nth-of-type(" + jump + ")", oElement).find(options.caption).fadeIn(options.speed); // Fade in caption
                            }
                            oCurrent = parseInt(jump); // Set current item
                        }
                        else if (oCurrent < oItemsLength) { // If current slide is not last
                            if (options.caption) { // Check if captions is defined
                                oTargetItem.next().find(options.caption).fadeIn(options.speed); // Fade in caption
                            }
                            oCurrent++; // Plus 1 to current item
                        }
                        else {
                            if (options.caption) { // Check if captions is defined
                                $(options.items + ":first-of-type", oElement).find(options.caption).fadeIn(options.speed); // Fade in caption
                            }
                            oCurrent = 1; // Set current item to 1
                        }
                        oTransitioning = false; // Set transitioning to false
                        setStackingOrder(); // Set stacking order ready for next transition
                        updatePager(); // Update pager links
                        updateLinks(); // Update controls (prev/next)
                    });
                }
            }

            function updatePager() {
                if (options.pagerClass) { // Check if pager class exists
                    $("ul." + options.pagerClass + " li a", oElement).removeClass(options.pagerCurrentClass); // Remove current item CSS class from all items
                    $("ul." + options.pagerClass + "  li:nth-child(" + oCurrent + ") a", oElement).addClass(options.pagerCurrentClass); // Add current item CSS class to target item
                }
            }

            function updateLinks() {
                if (oCurrent == oItemsLength) { // Check if current item is at end
                    $("a." + options.btnNextClass, oElement).addClass(options.btnDisabledClass); // Add disabled class to next button
                    $("a." + options.btnPrevClass, oElement).removeClass(options.btnDisabledClass); // Remove disabled class from previous button
                }
                else if (oCurrent == 1) { // Check if current item is at beginning
                    $("a." + options.btnPrevClass, oElement).addClass(options.btnDisabledClass); // Add disabled class to previous button
                    $("a." + options.btnNextClass, oElement).removeClass(options.btnDisabledClass); // Remove disabled class from next button
                }
                else {
                    $("a." + options.btnNextClass, oElement).add("a." + options.btnPrevClass, oElement).removeClass(options.btnDisabledClass); // Remove disabled class from previous and next button
                }
            }

            // Disable selection
            if ($.browser.mozilla) {//Firefox
                $(this).css('MozUserSelect', 'none');
            } else if ($.browser.msie) {//IE
                $(this).bind('selectstart', function () { return false; });
            } else {//Opera, etc.
                $(this).mousedown(function () { return false; });
            }

        });
    };
})(jQuery);
