(function (h, i, e) {
    var a = h.event,
        c, l;
    c = a.special.debouncedresize = {
        setup: function () {
            h(this).on("resize", c.handler)
        },
        teardown: function () {
            h(this).off("resize", c.handler)
        },
        handler: function (q, m) {
            var p = this,
                o = arguments,
                n = function () {
                    q.type = "debouncedresize";
                    a.dispatch.apply(p, o)
                };
            if (l) {
                clearTimeout(l)
            }
            m ? n() : l = setTimeout(n, c.threshold)
        },
        threshold: 100
    };
    Array.prototype.shuffle = function () {
        var n = this.length,
            o, m;
        while (n--) {
            o = Math.floor(Math.random() * n);
            m = this[n];
            this[n] = this[o];
            this[o] = m
        }
        return this
    };

    function j() {
        var n = ["webkit", "moz", "ms", "o"];
        if ("hidden" in document) {
            return "hidden"
        }
        for (var m = 0; m < n.length; m++) {
            if ((n[m] + "Hidden") in document) {
                return n[m] + "Hidden"
            }
        }
        return null
    }

    function b() {
        var m = j();
        if (!m) {
            return false
        }
        return document[m]
    }

    function g(m) {
        return Object.keys(m).length === 0
    }
    var d = h(i),
        f = i.Modernizr;
    h.GridRotator = function (n, o) {
        this.$el = h(o);
        if (f.backgroundsize) {
            var m = this;
            this.$el.addClass("ri-grid-loading");
            this._init(n)
        }
    };
    h.GridRotator.defaults = {
        rows: 4,
        columns: 10,
        w1024: {
            rows: 3,
            columns: 8
        },
        w768: {
            rows: 3,
            columns: 7
        },
        w480: {
            rows: 3,
            columns: 5
        },
        w320: {
            rows: 2,
            columns: 4
        },
        w240: {
            rows: 2,
            columns: 3
        },
        step: "random",
        maxStep: 3,
        preventClick: true,
        animType: "random",
        animSpeed: 800,
        animEasingOut: "linear",
        animEasingIn: "linear",
        interval: 3000,
        slideshow: true,
        onhover: false,
        nochange: []
    };
    h.GridRotator.prototype = {
        _init: function (m) {
            this.options = h.extend(true, {}, h.GridRotator.defaults, m);
            this._config()
        },
        _config: function () {
            var m = this,
                o = {
                    WebkitTransition: "webkitTransitionEnd",
                    MozTransition: "transitionend",
                    OTransition: "oTransitionEnd",
                    msTransition: "MSTransitionEnd",
                    transition: "transitionend"
                };
            this.supportTransitions = f.csstransitions;
            this.supportTransforms3D = f.csstransforms3d;
            this.transEndEventName = o[f.prefixed("transition")] + ".gridrotator";
            this.animTypes = this.supportTransforms3D ? ["fadeInOut", "slideLeft", "slideRight", "slideTop", "slideBottom", "rotateLeft", "rotateRight", "rotateTop", "rotateBottom", "scale", "rotate3d", "rotateLeftScale", "rotateRightScale", "rotateTopScale", "rotateBottomScale"] : ["fadeInOut", "slideLeft", "slideRight", "slideTop", "slideBottom"];
            this.animType = this.options.animType;
            if (this.animType !== "random" && !this.supportTransforms3D && h.inArray(this.animType, this.animTypes) === -1 && this.animType !== "showHide") {
                this.animType = "fadeInOut"
            }
            this.animTypesTotal = this.animTypes.length;
            this.$list = this.$el.children("ul");
            var n = 0,
                q = this.$list.find("img"),
                p = q.length;
            q.each(function () {
                var r = h(this),
                    s = r.attr("src");
                h("<img/>").load(function () {
                    ++n;
                    r.parent().css("background-image", "url(" + s + ")");
                    if (n === p) {
                        q.remove();
                        m.$el.removeClass("ri-grid-loading");
                        m.$items = m.$list.children("li");
                        m.$itemsCache = m.$items.clone();
                        m.itemsTotal = m.$items.length;
                        m.outItems = [];
                        m._layout(function () {
                            m._initEvents()
                        });
                        m._start()
                    }
                }).attr("src", s)
            })
        },
        _layout: function (v) {
            var w = this;
            this._setGridDim();
            this.$list.empty();
            this.$items = this.$itemsCache.clone().appendTo(this.$list);
            var m = this.$items.filter(":gt(" + (this.showTotal - 1) + ")"),
                n = m.children("a");
            this.outItems.length = 0;
            n.each(function (x) {
                w.outItems.push(h(this))
            });
            m.remove();
            var s = (document.defaultView) ? parseInt(document.defaultView.getComputedStyle(this.$el.get(0), null).width) : this.$el.width(),
                r = Math.floor(s / this.columns),
                q = s - (this.columns * Math.floor(r));
            for (var p = 0; p < this.rows; ++p) {
                for (var o = 0; o < this.columns; ++o) {
                    var u = this.columns * p + o,
                        t = this.$items.eq(u);
                    t.css({
                        width: o < Math.floor(q) ? r + 1 : r,
                        height: r
                    });
                    if (h.inArray(u, this.options.nochange) !== -1) {
                        t.addClass("ri-nochange").data("nochange", true)
                    }
                }
            }
            if (this.options.preventClick) {
                this.$items.children().css("cursor", "default").on("click.gridrotator", false)
            }
            if (v) {
                v.call()
            }
        },
        _setGridDim: function () {
            var m = this.$el.width();
            switch (true) {
                case (m < 240):
                    this.rows = this.options.w240.rows;
                    this.columns = this.options.w240.columns;
                    break;
                case (m < 320):
                    this.rows = this.options.w320.rows;
                    this.columns = this.options.w320.columns;
                    break;
                case (m < 480):
                    this.rows = this.options.w480.rows;
                    this.columns = this.options.w480.columns;
                    break;
                case (m < 768):
                    this.rows = this.options.w768.rows;
                    this.columns = this.options.w768.columns;
                    break;
                case (m < 1024):
                    this.rows = this.options.w1024.rows;
                    this.columns = this.options.w1024.columns;
                    break;
                default:
                    this.rows = this.options.rows;
                    this.columns = this.options.columns;
                    break
            }
            this.showTotal = this.rows * this.columns
        },
        _initEvents: function () {
            var n = this;
            d.on("debouncedresize.gridrotator", function () {
                n._layout()
            });
            var o = j();
            if (o) {
                var m = o.replace(/[H|h]idden/, "") + "visibilitychange";
                document.addEventListener(m, function () {
                    n._visChange()
                })
            }
            if (!f.touch && this.options.onhover) {
                n.$items.on("mouseenter.gridrotator", function () {
                    var p = h(this);
                    if (!p.data("active") && !p.data("hovered") && !p.data("nochange")) {
                        p.data("hovered", true);
                        n._replace(p)
                    }
                }).on("mouseleave.gridrotator", function () {
                    h(this).data("hovered", false)
                })
            }
        },
        _visChange: function () {
            b() ? clearTimeout(this.playtimeout) : this._start()
        },
        _start: function () {
            if (this.showTotal < this.itemsTotal && this.options.slideshow) {
                this._showNext()
            }
        },
        _getAnimType: function () {
            return this.animType === "random" ? this.animTypes[Math.floor(Math.random() * this.animTypesTotal)] : this.animType
        },
        _getAnimProperties: function (r) {
            var q = {},
                n = {},
                t = {},
                m = {},
                o = this._getAnimType(),
                s, p = 0;
            switch (o) {
                case "showHide":
                    s = 0;
                    m.opacity = 0;
                    break;
                case "fadeInOut":
                    m.opacity = 0;
                    break;
                case "slideLeft":
                    q.left = r.width();
                    t.left = 0;
                    m.left = -r.width();
                    break;
                case "slideRight":
                    q.left = -r.width();
                    t.left = 0;
                    m.left = r.width();
                    break;
                case "slideTop":
                    q.top = r.height();
                    t.top = 0;
                    m.top = -r.height();
                    break;
                case "slideBottom":
                    q.top = -r.height();
                    t.top = 0;
                    m.top = r.height();
                    break;
                case "rotateLeft":
                    s = this.options.animSpeed / 2;
                    q.transform = "rotateY(90deg)";
                    t.transform = "rotateY(0deg)";
                    p = s;
                    m.transform = "rotateY(-90deg)";
                    break;
                case "rotateRight":
                    s = this.options.animSpeed / 2;
                    q.transform = "rotateY(-90deg)";
                    t.transform = "rotateY(0deg)";
                    p = s;
                    m.transform = "rotateY(90deg)";
                    break;
                case "rotateTop":
                    s = this.options.animSpeed / 2;
                    q.transform = "rotateX(90deg)";
                    t.transform = "rotateX(0deg)";
                    p = s;
                    m.transform = "rotateX(-90deg)";
                    break;
                case "rotateBottom":
                    s = this.options.animSpeed / 2;
                    q.transform = "rotateX(-90deg)";
                    t.transform = "rotateX(0deg)";
                    p = s;
                    m.transform = "rotateX(90deg)";
                    break;
                case "scale":
                    s = this.options.animSpeed / 2;
                    q.transform = "scale(0)";
                    n.transform = "scale(1)";
                    t.transform = "scale(1)";
                    p = s;
                    m.transform = "scale(0)";
                    break;
                case "rotateLeftScale":
                    n.transform = "scale(1)";
                    s = this.options.animSpeed / 2;
                    q.transform = "scale(0.3) rotateY(90deg)";
                    t.transform = "scale(1) rotateY(0deg)";
                    p = s;
                    m.transform = "scale(0.3) rotateY(-90deg)";
                    break;
                case "rotateRightScale":
                    n.transform = "scale(1)";
                    s = this.options.animSpeed / 2;
                    q.transform = "scale(0.3) rotateY(-90deg)";
                    t.transform = "scale(1) rotateY(0deg)";
                    p = s;
                    m.transform = "scale(0.3) rotateY(90deg)";
                    break;
                case "rotateTopScale":
                    n.transform = "scale(1)";
                    s = this.options.animSpeed / 2;
                    q.transform = "scale(0.3) rotateX(90deg)";
                    t.transform = "scale(1) rotateX(0deg)";
                    p = s;
                    m.transform = "scale(0.3) rotateX(-90deg)";
                    break;
                case "rotateBottomScale":
                    n.transform = "scale(1)";
                    s = this.options.animSpeed / 2;
                    q.transform = "scale(0.3) rotateX(-90deg)";
                    t.transform = "scale(1) rotateX(0deg)";
                    p = s;
                    m.transform = "scale(0.3) rotateX(90deg)";
                    break;
                case "rotate3d":
                    s = this.options.animSpeed / 2;
                    q.transform = "rotate3d( 1, 1, 0, 90deg )";
                    t.transform = "rotate3d( 1, 1, 0, 0deg )";
                    p = s;
                    m.transform = "rotate3d( 1, 1, 0, -90deg )";
                    break
            }
            return {
                startInProp: q,
                startOutProp: n,
                endInProp: t,
                endOutProp: m,
                delay: p,
                animSpeed: s != e ? s : this.options.animSpeed
            }
        },
        _showNext: function (n) {
            var m = this;
            clearTimeout(this.playtimeout);
            this.playtimeout = setTimeout(function () {
                var t = m.options.step,
                    p = m.options.maxStep,
                    r = 1;
                if (p > m.showTotal) {
                    p = m.showTotal
                }
                var u = t === "random" ? Math.floor(Math.random() * p + r) : Math.min(Math.abs(t), p),
                    o = m._getRandom(u, m.showTotal);
                for (var q = 0; q < u; ++q) {
                    var s = m.$items.eq(o[q]);
                    if (s.data("active") || s.data("nochange")) {
                        m._showNext(1);
                        return false
                    }
                    m._replace(s)
                }
                m._showNext()
            }, n || Math.max(Math.abs(this.options.interval), 300))
        },
        _replace: function (o) {
            o.data("active", true);
            var n = this,
                r = o.children("a:last"),
                q = {
                    width: r.width(),
                    height: r.height()
                };
            o.data("active", true);
            var m = this.outItems.shift();
            this.outItems.push(r.clone().css("transition", "none"));
            m.css(q).prependTo(o);
            var p = this._getAnimProperties(r);
            m.css(p.startInProp);
            r.css(p.startOutProp);
            this._setTransition(m, "all", p.animSpeed, p.delay, this.options.animEasingIn);
            this._setTransition(r, "all", p.animSpeed, 0, this.options.animEasingOut);
            this._applyTransition(m, p.endInProp, p.animSpeed, function () {
                var u = h(this),
                    s = p.animSpeed === n.options.animSpeed && g(p.endInProp) ? p.animSpeed : 0;
                setTimeout(function () {
                    if (n.supportTransitions) {
                        u.off(n.transEndEventName)
                    }
                    u.next().remove();
                    u.parent().data("active", false)
                }, s)
            }, p.animSpeed === 0 || g(p.endInProp));
            this._applyTransition(r, p.endOutProp, p.animSpeed)
        },
        _getRandom: function (p, m) {
            var o = [];
            for (var n = 0; n < m; ++n) {
                o.push(n)
            }
            return o.shuffle().slice(0, p)
        },
        _setTransition: function (n, q, o, m, p) {
            setTimeout(function () {
                n.css("transition", q + " " + o + "ms " + m + "ms " + p)
            }, 25)
        },
        _applyTransition: function (o, n, q, r, p) {
            var m = this;
            setTimeout(function () {
                h.fn.applyStyle = m.supportTransitions ? h.fn.css : h.fn.animate;
                if (r && m.supportTransitions) {
                    o.on(m.transEndEventName, r);
                    if (p) {
                        r.call(o)
                    }
                }
                r = r || function () {
                    return false
                };
                o.stop().applyStyle(n, h.extend(true, [], {
                    duration: q + "ms",
                    complete: r
                }))
            }, 25)
        }
    };
    var k = function (m) {
        if (i.console) {
            i.console.error(m)
        }
    };
    h.fn.gridrotator = function (o) {
        var m = h.data(this, "gridrotator");
        if (typeof o === "string") {
            var n = Array.prototype.slice.call(arguments, 1);
            this.each(function () {
                if (!m) {
                    k("cannot call methods on gridrotator prior to initialization; attempted to call method '" + o + "'");
                    return
                }
                if (!h.isFunction(m[o]) || o.charAt(0) === "_") {
                    k("no such method '" + o + "' for gridrotator instance");
                    return
                }
                m[o].apply(m, n)
            })
        } else {
            this.each(function () {
                if (m) {
                    m._init()
                } else {
                    m = h.data(this, "gridrotator", new h.GridRotator(o, this))
                }
            })
        }
        return m
    }
})(jQuery, window);
