/*!
 * 图片预览
 */
var imagePreview = window.imagePreview || {};

imagePreview.Previewbox = (function () {
    var els = {},
        images = [],
        activeImage,
        initialized = false,
        selectors = [];

    return {
        radian: 0,
        horizontal: true,
        overlayOpacity: 0.85,
        animate: true,
        resizeSpeed: 8,
        borderSize: 10,
        toolbarSize: 40,
        labelImage: "Image",
        labelOf: "of",

        init: function () {
            this.resizeDuration = this.animate ? ((11 - this.resizeSpeed) * 0.15) : 0;
            this.overlayDuration = this.animate ? 200 : 0;

            if (!initialized) {
                this.initMarkup();
                this.initEvents();
                initialized = true;
            }

            this.rotate = this.initRotate();
        },

        initMarkup: function () {
            $(document.body).append("<iframe id='ux-previewbox-shim'></iframe>");
            els.shim = $('#ux-previewbox-shim');
            $(document.body).append("<div id='ux-previewbox-overlay'></div>");
            els.overlay = $('#ux-previewbox-overlay');
            var navboxTpl = this.getNavTemplate();
            $('#ux-previewbox-overlay').append(navboxTpl.join(''));
            var previewboxTpl = this.getTemplate();
            $(document.body).append(previewboxTpl.join(''));
            els.previewbox = $('#ux-previewbox-outerImageContainer');
            var ids =
                ['outerImageContainer', 'imageContainer', 'image', 'hoverNav', 'navPrev', 'navNext', 'loading', 'loadingLink',
                    'outerDataContainer', 'dataContainer', 'data', 'details', 'caption', 'imageNumber', 'bottomNav', 'navClose', 'leftRotate', 'rightRotate'];
            $.each(ids, function (index, id) {
                els[id] = $('#ux-previewbox-' + id);
            });
            $.each([els.overlay, els.previewbox, els.shim, els.navPrev, els.navNext], function (index, el) {
                el.hide();
            });
            var size = (this.animate ? 250 : 1) + 'px';
            els.outerImageContainer.css({
                width: size,
                height: size
            });
        },

        getNavTemplate: function () {
            return [
                '<div id="ux-previewbox-outerDataContainer">',
                '<div id="ux-previewbox-dataContainer">',
                '<div id="ux-previewbox-data">',
                '<div id="ux-previewbox-details">',
                '<span id="ux-previewbox-caption"></span>',
                '<span id="ux-previewbox-imageNumber"></span>',
                '</div>',
                '<div style="float:left">',
                '<input type="button" id="ux-previewbox-leftRotate" style="margin-left:20px;margin-bottom: 5px;" value="向左旋转"/>',
                '<input type="button" id="ux-previewbox-rightRotate"  value="向右旋转"/>',
                '<input type="button" id="ux-previewbox-navPrev" style="margin-left:20px;" value="上一张"/>',
                '<input type="button" id="ux-previewbox-navNext"  value="下一张"/>',
                '</div>',
                '<div id="ux-previewbox-bottomNav">',
                '<a href="#" id="ux-previewbox-navClose">',
                '<i class="fa fa-window-close-o" aria-hidden="true"></i>',
                '</a>',
                '</div>',
                '</div>',
                '</div>',
                '</div>'
            ];
        },
        getTemplate: function () {
            return [
//                '<div id="ux-previewbox">',
                '<div id="ux-previewbox-outerImageContainer">',
                '<div id="ux-previewbox-imageContainer">',
                '<img id="ux-previewbox-image">',
//                            '<div id="ux-previewbox-hoverNav">',
//                                '<a href="#" id="ux-previewbox-navPrev"></a>',
//                                '<a href="#" id="ux-previewbox-navNext"></a>',
//                            '</div>',
                '<div id="ux-previewbox-loading">',
                '<a id="ux-previewbox-loadingLink"></a>',
                '</div>',
                '</div>',
                '</div>'
//                '</div>'
            ];
        },
        resetRotate: function () {
            this.horizontal = true;
            this.radian = 0;
            this.rotate.dispose();
        },
        initRotate: function () {
            var css3Transform, container = els.outerImageContainer.dom, viewSize = this.getViewSize();
            function getMatrix(radian, x, y) {
                var Cos = Math.cos(radian.toFixed(5)), Sin = Math.sin(radian.toFixed(5));
                return {
                    M11: Cos.toFixed(10), M12: -Sin.toFixed(10),
                    M21: Sin.toFixed(10), M22: Cos.toFixed(10)
                };
            }

            var fn = {
                css3: {
                    support: function () {
                        var style = document.createElement("div").style, support = false;
                        $.each(
                            ["transform", "MozTransform", "webkitTransform", "OTransform"],
                            function (css) {
                                if (css in style) {
                                    css3Transform = css;
                                    support = true;
                                    return false;
                                }
                            });
                        return support;
                    }(),
                    init: function () {
                    },
                    load: function () {
                        els.outerImageContainer.css({
                            top: ( this.getViewSize()[1] - els.outerImageContainer.height() ) / 2 + "px",
                            left: ( this.getViewSize()[0] - els.outerImageContainer.width() ) / 2 + "px",
                            visibility: "visible"
                        });
                    },
                    show: function (obj) {
                        var matrix = getMatrix(obj.radian);
                        if (container) {
                            container.style[css3Transform] = "matrix("
                                + matrix.M11 + "," + matrix.M21 + ","
                                + matrix.M12 + "," + matrix.M22 + ", 0, 0)";
                        }
                    },
                    dispose: function () {
                        if(container){
                            container.style[css3Transform] = '';
                        }
                    }
                },
                filter: {
                    support: function () {
                        return "filters" in document.createElement("div");
                    }(),
                    init: function () {
                    },
                    show: function (obj) {
                        container.style.filter = "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand')";
                        var m = getMatrix(obj.radian);
                        container.filters.item(0).M11 = m.M11;
                        container.filters.item(0).M12 = m.M12;
                        container.filters.item(0).M21 = m.M21;
                        container.filters.item(0).M22 = m.M22;

                        if (obj.callback) obj.callback.call();
                    },
                    dispose: function () {
                        container.style.filter = "";
                    }
                },
                canvas: {//canvas设置
                    inited: false,
                    support: function () {
                        return "getContext" in document.createElement('canvas');
                    }(),
                    init: function () {
                        if (!this.inited) {
                            var canvas = this._canvas = document.createElement('canvas'),
                                context = this._context = canvas.getContext('2d');
                            //样式设置
                            $(document.body).append(canvas);
                            this.inited = true;
                        }

                    },
                    show: function (obj) {
                        this.init();
                        var bs = imagePreview.Previewbox.borderSize, ts = imagePreview.Previewbox.toolbarSize, img = els.image[0], context = this._context, canvas = this._canvas,
                            _left = (viewSize[0] - obj.w - bs * 2 ) / 2, _top = (viewSize[1] - bs * 2 - ts - obj.h) / 2;
                        $(canvas).css({'z-index': 15000, position: "absolute", left: _left + 'px', top: _top + 'px'});
                        canvas.width = obj.w + bs * 2;
                        canvas.height = obj.h + bs * 2;

                        //canvas变换
                        context.save();
                        context.clearRect(0, 0, img.width + bs * 2, img.height + bs * 2);//清空内容


                        context.fillStyle = "#f3efec";  //填充的颜色
                        context.fillRect(0, 0, obj.w + bs * 2, obj.h + bs * 2);


                        context.translate(obj.w / 2 + bs, obj.h / 2 + bs);//中心坐标
                        context.rotate(obj.radian);//旋转
                        context.drawImage(img, obj.hor ? -obj.w / 2 : -obj.h / 2, obj.hor ? -obj.h / 2 : -obj.w / 2, obj.hor ? obj.w : obj.h, obj.hor ? obj.h : obj.w);//居中画图
                        context.restore();
                        els.outerImageContainer.css({'display': 'none'});
                    },
                    dispose: function () {
                        this.inited = false;
                        if (this._canvas) {
                            $(this._canvas).remove();
                            this._canvas = this._context = null;
                        }
                        els.outerImageContainer.css({'display': 'block'});
                    }
                }
            };

            var rtv = null;
            $.each("css3|filter|canvas".toLowerCase().split("|"), function (index, type) {
                if (fn[type].support) {
                    rtv = fn[type];
                    return false;
                }
            }, this)
            return rtv;
        },
        rotateImage: function (radian) {
            var h = this.preload.height, w = this.preload.width, viewSize = this.getViewSize();
            this.horizontal = !this.horizontal;
            if (!this.horizontal) {
                var t = h;
                h = w;
                w = t;
            }

            var size = this.adjustSize(w, h), w = size.w, h = size.h;

            this.resizeImage(this.horizontal ? w : h, this.horizontal ? h : w, function () {

                this.rotate.show({
                    hor: this.horizontal,
                    radian: radian,
                    sw: this.preload.width,
                    sh: this.preload.height,
                    w: w,
                    h: h,
                    callback: function () {
                        els.outerImageContainer.css({
                            left: ($(window).scrollLeft() + (viewSize[0] - w - imagePreview.Previewbox.borderSize * 2) / 2) + 'px',
                            top: ($(window).scrollTop() + (viewSize[1] - h - imagePreview.Previewbox.borderSize * 2 - imagePreview.Previewbox.toolbarSize) / 2) + 'px'
                        });
                    }
                });
            });

        },

        initEvents: function () {
            var close = function (ev) {
                ev.preventDefault();
                imagePreview.Previewbox.close();
            };


            els.overlay.on('click', function (ev) {
                if (ev.target.id == 'ux-previewbox-overlay') {
                    imagePreview.Previewbox.close();
                }
            });
            els.loadingLink.on('click', close);
            els.navClose.on('click', close);


            els.leftRotate.on('click', function (ev) {
                ev.preventDefault();
                imagePreview.Previewbox.radian -= Math.PI / 2;
                imagePreview.Previewbox.rotateImage(imagePreview.Previewbox.radian);
            });
            els.rightRotate.on('click', function (ev) {
                ev.preventDefault();
                imagePreview.Previewbox.radian += Math.PI / 2;
                imagePreview.Previewbox.rotateImage(imagePreview.Previewbox.radian);
            });
            var zoom = 1,
                image = els.image,
                width = image.width(),
                height = image.height();
            els.previewbox.on('mousewheel', function (ev) {
                var delta = ev.originalEvent.wheelDelta;
                if (width == 0 && height == 0) {
                    width = image.width();
                    height = image.height();
                }
                if (delta > 0) {
                    zoom += 0.1;
                } else {
                    zoom -= 0.1;
                }
                if (zoom < 0.1) zoom = 0.1;
                imagePreview.Previewbox.resizeImage(width * zoom, height * zoom, null, true);
            });

            els.navPrev.on('click', function (ev) {
                ev.preventDefault();
                imagePreview.Previewbox.setImage(imagePreview.Previewbox.activeImage - 1);
            });

            els.navNext.on('click', function (ev) {
                ev.preventDefault();
                imagePreview.Previewbox.setImage(imagePreview.Previewbox.activeImage + 1);
            });
        },

        register: function (sel) {
            var sel = 'a[image=preview]';
            if (selectors.indexOf(sel) === -1) {
                selectors.push(sel);
                $(document).on('click', function (ev) {
                    if (ev.target.getAttribute("image") == "preview") {
                        ev.preventDefault();
                        imagePreview.Previewbox.open(ev.target, sel, true);
                    }
                });
            }
        },

        open: function (image, sel, group) {
            group = group || false;
            this.setViewSize();
            els.overlay.css({
                visibility: "visible",
                opacity: this.opacity
            });
            els.overlay.fadeIn(this.overlayDuration, function () {
                    imagePreview.Previewbox.images = [];
                    var index = 0;
                    if (!group) {
                        imagePreview.Previewbox.images.push([image.href, image.title]);
                    } else {
                        var setItems = $(sel);
                        $.each(setItems, function (idx, item) {

                            if (item.href) {
                                imagePreview.Previewbox.images.push([item.href, item.title]);
                            }
                        });

                        while (imagePreview.Previewbox.images[index] instanceof Array && imagePreview.Previewbox.images[index][0] != image.href) {
                            index++;
                        }
                    }

                    imagePreview.Previewbox.setImage(index);
                }
            );
        },

        setViewSize: function () {
            var win = $(window);
            var viewSize = this.getViewSize();
            els.overlay.css({
                height: win.scrollTop() + viewSize[1] + 'px'
            });
            els.shim.css({
                height: win.scrollTop() + viewSize[1] + 'px'
            }).show();
        },

        setImage: function (index) {
            this.activeImage = index;
            this.disableKeyNav();
            if (this.animate) {
                // calculate top and left offset for the previewbox
                var win = $(window);
                var previewboxTop = win.scrollTop() + win.height() / 2 - 50;//(Ext.lib.Dom.getViewportHeight() / 10);
                var previewboxLeft = win.scrollLeft() + win.width() / 2 - 50;
                els.previewbox.css({
                    position: 'absolute',
                    width: '100px',
                    height: '100px',
                    top: previewboxTop + 'px',
                    left: previewboxLeft + 'px'
                }).show();
                els.image.css({
                    width: '100px',
                    height: '100px'
                })

                els.loading.show();
            }

            els.image.hide();
//            els.hoverNav.hide();
            els.navPrev.hide();
            els.navNext.hide();
            els.imageNumber.hide();
            this.preload = new Image();
            this.preload.onload = (function () {
                els.image.attr("src", imagePreview.Previewbox.images[imagePreview.Previewbox.activeImage][0]);
                var as = imagePreview.Previewbox.adjustSize(imagePreview.Previewbox.preload.width, imagePreview.Previewbox.preload.height)
                imagePreview.Previewbox.resizeImage(as.w, as.h, imagePreview.Previewbox.resetRotate);
            });
            this.preload.src = this.images[imagePreview.Previewbox.activeImage][0];
        },

        adjustSize: function (w, h) {
            var wm = this.borderSize * 4, hm = this.borderSize * 4 + this.toolbarSize, viewSize = this.getViewSize(),
                iw = w + wm, ih = h + hm, vw = viewSize[0], vh = viewSize[1], vr = iw / vw, hr = ih / vh;
            if (vr > 1 || hr > 1) {
                if (vr < hr) {
                    w = w * ((vh - hm) / h);
                    h = vh - hm;
                } else {
                    h = h * ((vw - wm) / w);
                    w = vw - wm;
                }
            }
            return {w: w, h: h}
        },

        resizeImage: function (w, h, callback, noanimate) {
            var viewSize = this.getViewSize();
            var wCur = els.outerImageContainer.width();
            var hCur = els.outerImageContainer.height();

            var wNew = (w + this.borderSize * 2);
            var hNew = (h + this.borderSize * 2);

            var wDiff = wCur - wNew;
            var hDiff = hCur - hNew;

            var afterResize = function () {

                els.image.height(h + 'px');
                els.image.width(w + 'px');

                if (callback) callback.call(this);
                this.showImage(noanimate);
            };
            var win = $(window);
            if (hDiff != 0 || wDiff != 0) {
                els.outerImageContainer.css({
                    height: hNew + 'px',
                    width: wNew + 'px',
                    left: (win.scrollLeft() + (viewSize[0] - wNew) / 2) + 'px',
                    top: (win.scrollTop() + (viewSize[1] - 40 - hNew) / 2) + 'px'
                });
                afterResize.call(this);
            }
            else {
                afterResize.call(this);
            }
        },

        showImage: function (noanimate) {
            els.loading.hide();
            if (noanimate) {
                els.image.show();
            } else {
                els.image.fadeIn(this.resizeDuration,
                    function () {
                        imagePreview.Previewbox.updateDetails();
                    }
                );
            }
            this.preloadImages();
        },

        updateDetails: function () {
            var detailsWidth = els.data.width() - els.navClose.width() - 10;
            els.caption.empty();
            els.caption.append('<a title="下载" href="' + this.images[this.activeImage][0] + '" target="_self">' + this.images[this.activeImage][1] + '</a>');
            els.caption.show();
            if (this.images.length > 1) {
                els.imageNumber.text(this.labelImage + ' ' + (this.activeImage + 1) + ' ' + this.labelOf + '  ' + this.images.length);
                els.imageNumber.show();
            }

            els.dataContainer.fadeIn(this.resizeDuration / 2,
                function () {
                    var viewSize = imagePreview.Previewbox.getViewSize();
                    imagePreview.Previewbox.updateNav();
                });
        },

        updateNav: function () {

            this.enableKeyNav();

//            els.hoverNav.show();

            // if not first image in set, display prev image button
            if (imagePreview.Previewbox.activeImage > 0)
                els.navPrev.show();

            // if not last image in set, display next image button
            if (imagePreview.Previewbox.activeImage < (this.images.length - 1))
                els.navNext.show();
        },

        enableKeyNav: function () {
            $(document).on('keydown', this.keyNavAction);
        },

        disableKeyNav: function () {
            $(document).unbind('keydown', this.keyNavAction);
        },

        keyNavAction: function (ev) {
            var keyCode = ev.keyCode;

            if (
                keyCode == 88 || // x
                keyCode == 67 || // c
                keyCode == 27
            ) {
                imagePreview.Previewbox.close();
            }
            else if (keyCode == 80 || keyCode == 37) { // display previous image
                if (imagePreview.Previewbox.activeImage > 0) {
                    imagePreview.Previewbox.setImage(imagePreview.Previewbox.activeImage - 1);
                }
            }
            else if (keyCode == 78 || keyCode == 39) { // display next image
                if (imagePreview.Previewbox.activeImage < (imagePreview.Previewbox.images.length - 1)) {
                    imagePreview.Previewbox.setImage(imagePreview.Previewbox.activeImage + 1);
                }
            }
        },

        preloadImages: function () {
            var next, prev;
            if (this.images.length > imagePreview.Previewbox.activeImage + 1) {
                next = new Image();
                next.src = this.images[imagePreview.Previewbox.activeImage + 1][0];
            }
            if (imagePreview.Previewbox.activeImage > 0) {
                prev = new Image();
                prev.src = this.images[imagePreview.Previewbox.activeImage - 1][0];
            }
        },

        close: function () {
            this.disableKeyNav();
            this.rotate.dispose();
            els.previewbox.hide();
            els.overlay.fadeOut({
                duration: this.overlayDuration
            });
            els.shim.hide();
            //this.fireEvent('close', activeImage);
        },

        getViewSize: function () {
            return [$(window).width(), $(window).height()];
        }
    }
})();

$(document).ready(function () {
    imagePreview.Previewbox.init();
    imagePreview.Previewbox.register();
});