(function ($) {
    $.fn.jDiaporama = function (options) {

        var defaults = {
            auto: true,
            delay: 3000,
            animationSpeed: "normal",
            controls: true,
            showBullets: true,
            showLegend: true,
            alt: false,
            showCounter: true,
            onrollover: true,
            random: false,
            width: 0,
            height: 0
        };

        options = $.extend(defaults, options);

        var imageIndexProvider = new function () {
            this.nombreImages = 0;
            this.aleatoire = false;
            this.pointer = 0;
            this.lastImage = 0;
            this.table = [];

            this.getNextImageNumber = function () {
                var nextImage = this.table[this.pointer];
                this.pointer++;
                if (this.pointer >= this.nombreImages) {
                    this.pointer = 0;
                    if (this.aleatoire) this.randomizeTable();
                }
                return nextImage + 1;

            };

            this.getPreviousImageNumber = function () {
                this.pointer--;
                if (this.pointer < 0) {
                    this.pointer = this.nombreImages - 1;
                    if (this.aleatoire) this.randomizeTable();
                }
                var tempPointer = this.pointer == 0 ? this.nombreImages - 1 : this.pointer - 1;
                return this.table[tempPointer] + 1;
            };

            this.peek = function () {
                return this.table[this.pointer];
            };

            this.init = function (nombreImages, aleatoire) {
                this.nombreImages = nombreImages;
                this.aleatoire = aleatoire;
                this.table = new Array(this.nombreImages);
                for (var i = 0; i < this.nombreImages; i++) {
                    this.table[i] = i;
                }
                if (this.aleatoire) {
                    this.randomizeTable();
                }
                this.pointer = 0;
            };

            this.randomizeTable = function () {
                if (this.nombreImages < 3) return;
                for (var i = 0; i < this.nombreImages * 2; i++) {
                    var x = Math.floor(Math.random() * this.nombreImages);
                    var y = Math.floor(Math.random() * this.nombreImages);
                    var temp = this.table[x];
                    this.table[x] = this.table[y];
                    this.table[y] = temp;
                }
                while (this.table[0] == this.lastImage) {
                    this.randomizeTable();
                }
                this.lastImage = this.table[this.nombreImages - 1];
            };

            this.movePointerToImage = function(imageNumber) {
                if (imageNumber < 0 || imageNumber >= this.nombreImages) return;
                var tempPointer = 0;
                while (this.table[tempPointer] != imageNumber) tempPointer++;
                this.pointer = ((tempPointer < 1) ? this.nombreImages : tempPointer) - 1;
            };
        };

        this.each(function () {
            var diapo = $(this);
            if ($("li", diapo).length > 1) {
                var mouseover = false;
                var nbSlides = $("li", diapo).length;
                var pause = false;
                diapo.wrap("<div class='jDiaporama'></div>");

                imageIndexProvider.init(nbSlides, options.random);

                diapo.parent().mouseenter(function () {
                    mouseover = true;
                    if (options.onrollover) {
                        displayInfos($("li.active", diapo), "show");
                        if (options.showBullets)
                            diapo.siblings(".jDiaporama_status").fadeIn("fast");
                    }

                    if (options.controls)
                        diapo.siblings(".jDiaporama_controls").fadeIn("fast");


                }).mouseleave(function () {
                    mouseover = false;
                    if (options.onrollover) {
                        displayInfos($("li.active", diapo), "hide");

                        if (options.showBullets)
                            diapo.siblings(".jDiaporama_status").fadeOut("fast");
                    }

                    if (options.controls)
                        diapo.siblings(".jDiaporama_controls").fadeOut("fast");
                });

                function init() {

                    diapo.width(options.width);
                    diapo.height(options.height);
                    diapo.parent().width(options.width);
                    diapo.parent().height(options.height);

                    if (!options.onrollover)
                        displayInfos($("li", diapo), "show");

                    if (options.showBullets) {
                        diapo.siblings(".jDiaporama_status").show();
                        $("#jDiaporama_bullet_" + (parseInt($("li", diapo).index($("li:first-child", diapo))) + 1), diapo.siblings()).addClass("active");
                    }
                }


                diapo.width(options.width);
                diapo.height(options.height);
                diapo.parent().width(options.width);
                diapo.parent().height(options.height);

                var inter = "";

                if (options.auto)
                    inter = setTimeout(function () { next(); }, options.delay);

                $("li", diapo).hide();
                diapo.show();

                $("li", diapo).each(function () {
                    var elt = $("img", $(this));
                    elt.css("margin-top", (options.height - elt.height()) / 2 + "px");
                    elt.css("margin-left", (options.width - elt.width()) / 2 + "px");
                });

                var current = imageIndexProvider.getNextImageNumber();
                $("li:nth-child(" + current + ")", diapo).addClass("active");
                $("li:nth-child(" + current + ")", diapo).fadeIn(options.animationSpeed, init);

                $("li", diapo).each(function () {
                    var elt = $(this);

                    var i = parseInt($("li", diapo).index($(this)) + 1);
                    $(this).attr("id", "jDiaporama_image_" + i);

                    if (options.showLegend) {
                        var hasTitle = ($("img", elt).attr("title") != "");
                        if (hasTitle)
                            elt.append("<div class='desc'>" + $("img", elt).attr("title") + "</div>");
                    }
                    if (options.alt) {
                        var hasAlt = ($("img", elt).attr("alt") != "");
                        if (hasAlt)
                            elt.append("<div class='title'>" + $("img", elt).attr("alt") + "</div>");
                    }

                    if (options.showCounter)
                        elt.append("<div class='count'>" + parseInt($("li", diapo).index(elt) + 1) + "/" + diapo.children().length + "</div>");

                });

                // Controls
                if (options.showBullets) {
                    // Etat du diaporama
                    diapo.after("<div class='jDiaporama_status'></div>");
                    $("li", diapo).each(function () {
                        var i = parseInt($("li", diapo).index($(this)) + 1);
                        $(".jDiaporama_status", diapo.parent()).append("<a id='jDiaporama_bullet_" + i + "' href='#'>Image " + i + "</a>");
                    });
                    $(".jDiaporama_status", diapo.parent()).css("padding-left", (options.width / 2) - (nbSlides * 8)); // bullet is 10px wide + 6px margin
                    $(".jDiaporama_status", diapo.parent()).css("-moz-box-sizing", "border-box");
                    $(".jDiaporama_status", diapo.parent()).css("-webkit-box-sizing", "border-box");
                    $(".jDiaporama_status", diapo.parent()).css("box-sizing", "border-box");

                    $(".jDiaporama_status a", diapo.parent()).click(function () {
                        if ($("li.active", diapo).attr("id").split("_")[2] != $(this).attr("id").split("_")[2]) {
                            imageIndexProvider.movePointerToImage($(this).attr("id").split("_")[2]);
                            next();
                        }
                        return false;
                    });
                }

                if (options.controls) {

                    diapo.after("<div class='jDiaporama_controls'><a href='#' class='prev'>Prec.</a> " + ((options.auto) ? "<a href='#' class='pause'>Pause</a>" : "") + " <a href='#' class='next'>Suiv.</a></div>");

                    $(".prev", diapo.siblings()).click(function () {
                        prev();
                        return false;
                    });

                    $(".next", diapo.siblings()).click(function () {
                        next();
                        return false;
                    });

                    $(".pause", diapo.siblings()).click(function () {
                        if ($(this).hasClass("pause")) {
                            $(this).removeClass("pause").addClass("play");
                            clearInterval(inter);
                            pause = true;
                        }
                        else {
                            $(this).removeClass("play").addClass("pause");
                            inter = setTimeout(function () { next() ; }, options.delay);
                            pause = false;
                        }

                        return false;
                    });
                }

                function next() {
                    nextImage($("li#jDiaporama_image_" + imageIndexProvider.getNextImageNumber(), diapo));
                }

                function prev() {
                    nextImage($("li#jDiaporama_image_" + imageIndexProvider.getPreviousImageNumber(), diapo));
                }

                function nextImage(elt) {
                    clearInterval(inter);
                    $("li.active", diapo).fadeOut(options.animationSpeed).removeClass("active");
                    $(".jDiaporama_status a", diapo.parent()).removeClass("active");

                    var id = elt.attr("id").split("_")[2];
                    $("li#jDiaporama_image_" + id, diapo).addClass("active").fadeIn(options.animationSpeed,
                    function () { if (options.auto && !pause) inter = setTimeout(function () { next(); }, options.delay); });

                    if (options.showBullets)
                        $("#jDiaporama_bullet_" + id, diapo.siblings()).addClass("active");

                    if (options.showLegend && mouseover && options.onrollover)
                        displayInfos($("li.active", diapo), "show");
                    else if (!mouseover && options.onrollover)
                        displayInfos($("li.active", diapo), "hide");

                }

                function displayInfos(elt, display) {
                    var hasTitle = ($("img", elt).attr("title") != "");
                    var hasAlt = ($("img", elt).attr("alt") != "");

                    if (hasTitle)
                        if (display == "show")
                            $(".desc", elt).slideDown("fast");
                        else
                            $(".desc", elt).slideUp("fast");

                    if (hasAlt)
                        if (display == "show")
                            $(".title", elt).slideDown("fast");
                        else
                            $(".title", elt).slideUp("fast");

                    if (options.showCounter)
                        if (display == "show")
                            $(".count", elt).slideDown("fast");
                        else
                            $(".count", elt).slideUp("fast");
                }
            }
        });
        return this;
    };
})(jQuery);
