/** 
* @projectDescription JsFlickrGallery - Simple JavaScript Flickr gallery,
* http://petejank.github.io/js-flickr-gallery/
* 
* @version 1.24
* @author   Peter Jankowski http://likeadev.com
* @license  MIT license.
*/
; (function(f, j, p, h) {
    var x = "json",
    r = "flickr.photos.search",
    q = "flickr.photosets.getPhotos",
    v = "62525ee8c8d131d708d33d61f29434b6",
    k = "data-tags",
    e = "data-user-id",
    u = "data-set-id",
    i = "data-per-page",
    c = "data-gallery-id",
    g = "jsfg",
    t = 767,
    w = 10000,
    n = "modal-header",
    s = "h3",
    d = "modal-body",
    m = "modal-image",
    o = "modal-footer";
    var a = "jsFlickrGallery",
    l = {
        fetchImages: true,
        animation: "fade",
        animationSpeed: 250,
        preload: {
            range: 2
        },
        structure: {
            ulClass: ".thumbnails",
            liClass: ".span1",
            aClass: ".thumbnail"
        },
        modal: {
            generate: true,
            id: "jsfg-modal",
            title: "." + n + " " + s,
            imageContainerClass: "." + m,
            onContainerNext: true,
            imageFadeTime: 250,
            prevClass: ".btn.modal-prev",
            nextClass: ".btn.modal-next",
            prevText: "Previous image",
            nextText: "Next image",
            offsetWidth: 100,
            offsetHeight: 200
        },
        pagination: {
            generate: true,
            containerClass: ".pagination",
            prevClass: ".btn.pagination-prev",
            nextClass: ".btn.pagination-next",
            prevText: "Previous page",
            nextText: "Next page"
        },
        loader: {
            animation: true,
            loaderClass: ".jsfg-loader",
            text: "Loading",
            interval: 200,
            mark: ".",
            markClass: ".animation-marks",
            maxMarks: 3
        },
        url: {
            per_page: 30,
            tag_mode: "all"
        },
        error: {
            text: "No photos found",
            tagClass: "error"
        },
        imageSizes: {
            small: "s",
            medium_100: "t",
            medium: "q",
            medium_640: "z",
            large: "b",
            original: "o"
        },
        apiUrl: "https://api.flickr.com/services/rest/?jsoncallback=?",
        setDefaultSize: function() {
            this.thumbnailSize = this.imageSizes.medium;
            this.imageSize = this.imageSizes.large
        }
    };
    function b(z, y) {
        this.element = z;
        this.$element = f(z);
        this.options = f.extend(true, {},
        l, y);
        this.paginationContext = this.options.pagination && this.options.pagination.generate ? this.element : p;
        if (!this.options.thumbnailSize && !this.options.imageSize) {
            this.options.setDefaultSize()
        }
        this.galleryId = this.element.id || Math.random().toString(36);
        this.page = 1;
        this.init()
    }
    b.prototype = {
        init: function() {
            if (this.options.fetchImages) {
                if (this.options.loader) {
                    this.loaderInterval = this._createLoader(this.element)
                }
                this.createGallery()
            } else {
                this.anchors = this._getAnchors()
            }
            if (this.options.pagination && this.options.fetchImages) {
                if (this.options.pagination.generate) {
                    this._createPagination()
                }
                this._bindPaginationEvents()
            }
            if (this.options.modal) {
                if (this.options.modal.generate) {
                    this._createModal()
                }
                this._bindModalEvents()
            }
        },
        createGallery: function(y) {
            this.options.url.format = x;
            this.options.url.api_key = v;
            this.options.url.photoset_id = this.$element.attr(u) || this.options.url.photoset_id;
            if (this.options.url.photoset_id) {
                this.options.url.method = q;
                delete this.options.url.tag_mode
            } else {
                this.options.url.method = r;
                delete this.options.url.photoset_id;
                this.options.url.tags = this.$element.attr(k) || this.options.url.tags;
                this.options.url.user_id = this.$element.attr(e) || this.options.url.user_id;
                if (!this.options.url.user_id) {
                    delete this.options.url.user_id
                }
            }
            this.options.url.page = this.page = y || this.page;
            this.options.url.per_page = this.$element.attr(i) || this.options.url.per_page;
            this._getPhotos();
            return this
        },
        clearGallery: function(A) {
            var z = f(this.options.structure.ulClass, this.element),
            y = this;
            switch (this.options.animation) {
                case "fade":
                    z.fadeOut(this.options.animationSpeed, B);
                    break;
                case "show":
                    z.hide(this.options.animationSpeed, B);
                    break;
                case false:
                    z.hide(0, B)
            }
            function B() {
                if (y.options.loader) {
                    y.loaderInterval = y._createLoader(y.element)
                }
                if (A) {
                    y.createGallery(A)
                }
                z.remove()
            }
            return this
        },
        isLastPage: function() {
            return (!this.anchors || this.anchors.length < this.options.url.per_page) ? true : false
        },
        nextPage: function() {
            if (!this.isLastPage()) {
                return this.clearGallery(this.page + 1)
            } else {
                return false
            }
        },
        prevPage: function() {
            if (this.page > 1) {
                return this.clearGallery(this.page - 1)
            } else {
                return false
            }
        },
        prevImage: function() {
            this.index -= 1;
            if (this.index < 0) {
                this.index = this.anchors.length - 1
            }
            return this._loadImage(false)
        },
        nextImage: function() {
            this.index += 1;
            if (this.index > this.anchors.length - 1) {
                this.index = 0
            }
            return this._loadImage(false)
        },
        _getPhotos: function() {
            var y = this;
            f.ajax({
                type: "GET",
                url: y.options.apiUrl,
                data: y.options.url,
                dataType: "jsonp",
                timeout: w
            }).done(function(z) {
                y._renderGalleryContent(z.photos || z.photoset)
            }).always(function(z, A) {
                if (A === "timeout") {
                    y._getPhotos()
                }
            })
        },
        _renderGalleryContent: function(I) {
            var J = this,
            y, B, z = "",
            D = 0,
            F, H, E, C = this._replaceDots(J.options.structure.liClass),
            G = this._replaceDots(J.options.structure.aClass);
            if (I.photo.length > 0) {
                B = f('<ul class="' + this._replaceDots(J.options.structure.ulClass) + '" style="display: none">');
                for (var A = 0; A < I.photo.length; A++) {
                    F = "https://farm" + I.photo[A].farm + ".static.flickr.com/" + I.photo[A].server + "/" + I.photo[A].id + "_" + I.photo[A].secret + "_";
                    H = this._htmlEscape(I.photo[A].title);
                    z += '<li class="' + C + '"><a href="' + F + J.options.imageSize + '.jpg" title="' + H + '" class="' + G + '" target="_blank"><img alt="' + H + '" src="' + F + J.options.thumbnailSize + '.jpg"/></a></li>'
                }
                J.element.insertBefore(B.append(z)[0], J.element.firstChild);
                y = B.find("img");
                y.on("error",
                function() {
                    var K = f(this),
                    L = K.attr("src");
                    K.attr("src", null).attr("src", L)
                });
                y.on("load",
                function() {
                    D++;
                    if (D === I.photo.length) {
                        J._removeLoader(J.element);
                        switch (J.options.animation) {
                            case "fade":
                                B.fadeIn(J.options.animationSpeed);
                                break;
                            case "show":
                                B.show(J.options.animationSpeed);
                                break;
                            case false:
                                B.show()
                        }
                        y.off("load").off("error");
                        J.anchors = J._getAnchors();
                        J._togglePagination()
                    }
                })
            } else {
                E = p.createElement("span");
                E.className = J.options.error.tagClass;
                E.innerHTML = J.options.error.text;
                J.element.insertBefore(E, J.element.firstChild);
                J._removeLoader(J.element)._togglePagination()
            }
            return J
        },
        _createPagination: function() {
            var y = "",
            A = f(this.options.pagination.prevClass, this.paginationContext)[0],
            z = f(this.options.pagination.nextClass, this.paginationContext)[0];
            if (!A && !z && this.options.pagination.generate) {
                y += '<div class="' + this._replaceDots(this.options.pagination.containerClass) + '"><button class="' + this._replaceDots(this.options.pagination.prevClass) + '" title="' + this.options.pagination.prevText + '" disabled="disabled">&laquo;</button><button class="' + this._replaceDots(this.options.pagination.nextClass) + '" title="' + this.options.pagination.nextText + '" disabled="disabled">&raquo;</button></div>';
                this.element.appendChild(f(y)[0])
            }
            return this
        },
        _bindPaginationEvents: function() {
            var A = this,
            z = f(this.options.pagination.prevClass, this.paginationContext),
            y = f(this.options.pagination.nextClass, this.paginationContext);
            z.click(function() {
                if (!z.is(":disabled")) {
                    y.attr("disabled", "disabled");
                    z.attr("disabled", "disabled");
                    A.prevPage()
                }
            });
            y.click(function() {
                if (!y.is(":disabled")) {
                    z.attr("disabled", "disabled");
                    y.attr("disabled", "disabled");
                    A.nextPage()
                }
            })
        },
        _togglePagination: function() {
            var z = f(this.options.pagination.prevClass, this.paginationContext),
            y = f(this.options.pagination.nextClass, this.paginationContext);
            if (this.page !== 1) {
                z.removeAttr("disabled")
            } else {
                z.attr("disabled", "disabled")
            }
            if (!this.isLastPage()) {
                y.removeAttr("disabled")
            } else {
                y.attr("disabled", "disabled")
            }
            return this
        },
        _createModal: function() {
            var B, y, A, z;
            if (!p.getElementById(this.options.modal.id)) {
                B = '<div class="' + n + '"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><' + s + "></" + s + "></div>";
                y = '<div class="' + d + '"><div class="' + m + '"></div></div>';
                A = '<div class="' + o + '"><button title="' + this.options.modal.prevText + '" class="' + this._replaceDots(this.options.modal.prevClass) + '">&laquo;</button><button title="' + this.options.modal.nextText + '" class="' + this._replaceDots(this.options.modal.nextClass) + '">&raquo;</button></div>';
                z = p.createElement("div");
                z.id = this.options.modal.id;
                z.className = "modal jsfg-modal hide fade";
                z.innerHTML = B + y + A;
                p.body.appendChild(z)
            }
            return this
        },
        _bindModalEvents: function() {
            var y = this,
            B = this.options.modal.onContainerNext ? this.options.modal.nextClass + ", " + this.options.modal.imageContainerClass : this.options.modal.nextClass,
            z = f("#" + y.options.modal.id),
            A = "#" + this.options.modal.id;
            this.$element.on("click", this.options.structure.aClass,
            function(D) {
                var C;
                D.preventDefault();
                z.attr(c, y.galleryId);
                for (C = 0; C < y.anchors.length; C++) {
                    if (y.anchors[C] === this) {
                        y.index = C
                    }
                }
                y._loadImage(true)
            });
            f(B, A).click(function(C) {
                C.preventDefault();
                if (z.attr(c) === y.galleryId) {
                    y.nextImage()
                }
            });
            f(this.options.modal.prevClass, A).click(function(C) {
                C.preventDefault();
                if (z.attr(c) === y.galleryId) {
                    y.prevImage()
                }
            });
            return this
        },
        _loadImage: function(C) {
            var G = this,
            E = f("#" + this.options.modal.id),
            D = f(this.options.modal.title, E),
            y = G.index,
            F = f(this.anchors[this.index]),
            A = f("<img/>"),
            B = f(this.options.modal.imageContainerClass, E),
            z = f(j);
            B.children().hide();
            D.text(F.attr("title"));
            if (C) {
                E.modal("show")
            }
            A.on("error",
            function() {
                A.prop("src", null).prop("src", F.attr("href"))
            });
            A.on("load",
            function() {
                if (G.index === y) {
                    B.children().remove();
                    G._removeLoader(B[0]);
                    A = G._resizeToFit(A, z);
                    D.width(A.prop("width"));
                    B.height(A.prop("height")).width(A.prop("width"));
                    A.appendTo(B);
                    if (z.width() > t) {
                        E.css("top", ""); (f.support.transition ? E.animate : E.css).call(E.stop(), {
                            "margin-left": -E.outerWidth() / 2,
                            "margin-top": -E.outerHeight() / 2
                        })
                    } else {
                        E.css({
                            top: (z.height() - E.outerHeight()) / 2,
                            "margin-left": "",
                            "margin-top": ""
                        })
                    }
                    A.fadeIn(G.options.modal.imageFadeTime);
                    if (G.options.preload) {
                        G._preloadImages()
                    }
                }
                A.off("load").off("error")
            });
            A.prop("src", F.attr("href")).attr("alt", F.attr("title"));
            if (!A[0].complete) {
                this.loaderInterval = this._createLoader(B[0])
            }
            return this
        },
        _preloadImages: function() {
            var B = this.index + this.options.preload.range + 1,
            z = this.index - this.options.preload.range,
            y, A, C;
            B = B > this.anchors.length ? B - this.anchors.length : B;
            z = z > B ? z - this.anchors.length : z;
            for (A = z; A < B; A++) {
                C = A < 0 ? this.anchors.length + A : A;
                y = this.anchors[C];
                if (y && C !== this.index) {
                    f(p.createElement("img")).attr("src", y.href || f(y).attr("href"))
                }
            }
            return this
        },
        _resizeToFit: function(B, z) {
            var E = 1,
            D, C, A = B.prop("width"),
            y = B.prop("height");
            D = z.width() - this.options.modal.offsetWidth;
            C = z.height() - this.options.modal.offsetHeight;
            if (A > D || y > C) {
                E = Math.min(D / A, C / y)
            }
            B.prop("width", A * E).prop("height", y * E);
            return B
        },
        _createLoader: function(A) {
            var z = p.createElement("span"),
            B = p.createElement("p"),
            y = this.options;
            B.appendChild(p.createTextNode(y.loader.text));
            B.className = this._replaceDots(y.loader.loaderClass);
            z.className = this._replaceDots(y.loader.markClass);
            A.insertBefore(B.appendChild(z).parentNode, A.firstChild);
            if (y.loader.animation) {
                return setInterval(function() {
                    if (z.innerHTML.length <= y.loader.maxMarks) {
                        z.innerHTML += y.loader.mark
                    } else {
                        z.innerHTML = ""
                    }
                },
                y.loader.interval)
            } else {
                return true
            }
        },
        _getAnchors: function() {
            return f(this.options.structure.aClass, this.element).get()
        },
        _removeLoader: function(z) {
            var y = f(this.options.loader.loaderClass, z)[0];
            if (this.loaderInterval && y) {
                z.removeChild(y);
                clearInterval(this.loaderInterval)
            }
            return this
        },
        _htmlEscape: function(y) {
            return y.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
        },
        _replaceDots: function(y) {
            return y.replace(/\./g, " ")
        }
    };
    f.fn[a] = function(y) {
        return this.each(function() {
            if (!f.data(this, "plugin_" + a)) {
                f.data(this, "plugin_" + a, new b(this, y))
            }
        })
    };
    f(function() {
        f('[data-toggle="' + g + '"]').jsFlickrGallery()
    })
})(jQuery, window, document);