(function ($) {
    /**
     * 多文件上传控件,用于上传文件的控件,支持多文件,格式限制,图片预览,文件大小限制等功能。
     *
     *     @example
     *     var file = new FR.MultiFileEditor({
     *          renderEl : 'body'
     *     });
     *
     * @class FR.MultiFileEditor
     * @extends FR.BaseEditor
     *
     * @cfg {JSON} options 属性配置
     * @cfg {Number} [options.width=120] 宽度
     * @cfg {Number} [options.height=20] 高度
     * @cfg {Boolean} [options.render=true] 是否渲染
     * @cfg {Boolean} [options.showViewImage=true] 编辑完显示预览图片
     */
    FR.MultiFileEditor = FR.extend(FR.BaseEditor, /**@class FR.MultiFileEditor*/{
        /**
         * @returns {*}
         * @private
         */
        _defaultConfig: function () {
            return $.extend(FR.MultiFileEditor.superclass._defaultConfig.apply(), {
                width: 120, // 预览面板的宽度
                height: 20, // 预览面板的高度
                render: true,
                // 编辑完显示预览图片
                showViewImage: true
            });
        },
        /**
         * @private
         */
        _init: function () {
            FR.$defaultImport('/com/fr/web/core/js/noswfupload.js', 'js');
            FR.$defaultImport('/com/fr/web/core/css/widget/noswfupload-icons.css',
                'css');
            FR.MultiFileEditor.superclass._init.apply(this, arguments);
            var o = this.options;
            var self = this;
            this.$uploadForm = $('<form enctype="multipart/form-data"></form>')
                .css('position', 'relative').appendTo(this.element);
            this.divWrap = $("<div></div>").css({
                'width': this.options.width + 'px',
                'height': this.options.height + 'px',
                'position': 'relative',
                'overflow': 'hidden'
            }).appendTo(this.$uploadForm);
            this.$fileupload = $('<input type="file" name="file"/>')
                .addClass('fr-fileupload').appendTo(this.divWrap);
            // be sure input accept multiple files
            if (o.maxlength !== 1) {
                this.$fileupload[0].setAttribute("multiple", "multiple");
            }
            if (o.disabled) {
                this.$fileupload[0].setAttribute("disabled", "disabled");
            }

            // 添加预览面板
            if (o.render === true) {
                var min = Math.min(this.options.height, this.options.width);
                var pImageSize = min > 32 ? 32 : min - 2;
                var pCountSize = min > 32 ? 20 : min * 0.7;
                this.$previewImage = $("<img>").attr("src", FR.servletURL + "?op=resource&resource=/com/fr/web/images/file/upload.gif")
                    .appendTo(this.divWrap).addClass("fr-fileupload-image")
                    .css({
                        left: this.options.width > 32 ?
                            (this.options.width - 32) / 2 : 0,
                        top: this.options.height > 32 ?
                            (this.options.height - 32) / 2 : 0,
                        width: pImageSize,
                        height: pImageSize
                    });

                if (o.tooltipText) {
                    var toolSpan = $("<span/>").addClass("fr-fileupload-tooltipspan");
                    this.tooltipDiv = $("<div/>").css({
                        left: pImageSize + 7 + 'px',
                        height: pImageSize + 'px'
                    }).append(toolSpan.text(o.tooltipText)).addClass("fr-fileupload-tooltip").appendTo(this.$uploadForm);
                }
                this.$preview = this.$previewImage;
                if (self.options.maxlength !== 1) {
                    this.$previewCount = $('<div class="fr-fileupload-preview-count"/>').text(0)
                        .appendTo(this.divWrap).css({
                            left: this.options.width > 32 ?
                                (this.options.width - 32) / 2 + 22 : this.$previewImage.width() - 10,
                            top: this.options.height > 32 ?
                                (this.options.height - 32) / 2 + 8 : 0,
                            width: pCountSize,
                            height: pCountSize,
                            'border-radius': pCountSize,
                            'font-size': pCountSize * 0.6
                        });
                }
            } else {
                this.$preview = this.element;
            }
            if (this.options.write) {
                $('.fr-fileupload', self.element).css({
                    'right': 0,
                    'font-size': self.element.height() < 100
                        ? '100px'
                        : self.element.height() + 'px',
                    'width': this.options.width,
                    'height': this.options.height
                });
            }
            // create the noswfupload.wrap Object
            // wrap.maxSize 文件大小限制
            // wrap.maxlength 文件个数限制
            this.wrap = noswfupload.wrap((this.$fileupload)[0], o.maxSize, o.maxlength,
                this.options.width, this.options.height);
            var wrap = this.wrap;
            // fileType could contain whatever text but filter checks *.{extension}
            // if present

            // handlers
            wrap.onerror = function () {
                noswfupload.text(this.dom.info, "WARNING: Unable to upload "
                    + this.file.fileName);
            };

            wrap.onloadstart = function (rpe, xhr) {
                this.show(0, 0);
                noswfupload.text(this.dom.info, "Preparing for upload ... ");
            };

            wrap.onprogress = function (rpe, xhr) {
                // percent for each bar
                this.show((this.sent + rpe.loaded) * 100 / this.total, rpe.loaded * 100 / rpe.total);

                noswfupload.text(this.dom.info, FR.i18nText("FR-Basic-File_Uping_File") + ":  " + this.file.fileName);

                // fileSize is -1 only if browser does not support file info access
                // this if splits recent browsers from others
                if (this.file.fileSize !== -1) {
                    // simulation property indicates when the progress event is fake
                    if (rpe.simulation) {
                        noswfupload.text(this.dom.info,
                            FR.i18nText("FR-Basic-File_Uping_File") + ":  " + this.file.fileName,
                            FR.i18nText("FR-Basic-File_All_File_Uploaded") + noswfupload.size(this.sent + rpe.loaded));
                    } else {
                        noswfupload.text(this.dom.info,
                            FR.i18nText("FR-Basic-File_Uping_File") + ":  " + this.file.fileName,
                            FR.i18nText("FR-Basic-File_Uploaded_File") + ": " + noswfupload.size(rpe.loaded),
                            FR.i18nText("FR-Basic-File_All_File_Uploaded") + noswfupload.size(this.sent + rpe.loaded));
                    }
                } else {
                    // if fileSIze is -1 browser is using an iframe because it does
                    // not support
                    // files sent via Ajax (XMLHttpRequest)
                    // We can still show some information
                    noswfupload.text(this.dom.info,
                        "Uploading: " + this.file.fileName,
                        "Sent: " + (this.sent / 100) + " out of " + (this.total / 100));
                }
            };

            // generated if there is something wrong during upload
            wrap.onerror = function () {
                // just inform the user something was wrong
                noswfupload.text(this.dom.info, "WARNING: Unable to upload "
                    + this.file.fileName);
            };

            // generated when every file has been sent (one or more, it does not
            // matter)
            wrap.onload = function (rpe, xhr) {
                var self_ = this;
                // just show everything is fine ...
                noswfupload.text(this.dom.info, "Upload complete");

                // ... and after a second reset the component
                setTimeout(function () {
                    self_.clean(); // remove files from list
                    self_.hide(); // hide progress bars and enable input file

                    noswfupload.text(self_.dom.info, "");
                    self.fireEvent(FR.Events.AFTEREDIT);
                    // enable again the submit button/element
                }, 1000);
                self.showViewList();

                var attach =self.wrap.attach_array[0];

                self.fireEvent(FR.Events.CALLBACK, attach);
                // fileListWrap.parent().css("overflow", "auto");
            };
            wrap.url = this.options.url ? this.options.url : FR.servletURL
                + '?op=fr_attach&cmd=ah_upload';
            //传到不同的服务器上, 会导致httpsession相互覆盖, 处理起来更麻烦了
            wrap.url += ((window.FS && window.FS.serverID) ? '&serverID='+ window.FS.serverID : "");
            wrap.fileType = o.accept;   //文件类型限制
            wrap.attach_array = [];
            wrap.attach_names = [];
            wrap.attachNum = 0;
            this._dealValueWithEvents(o.value);
        },

        /**
         * @param {JSON} attach 文件对象
         * @private
         */
        _dealValueWithEvents: function (attach) {
            if (FR.equals(attach, this.wrap.attach_array)
                || (this.wrap.attach_array.length === 1 && FR.equals(
                this.wrap.attach_array[0], attach))) {
                return;
            }
            if (($.isArray(attach) && attach.length > 0 && attach[0].attach_id)
                || (attach && attach.attach_id)) {
                var attach_array = $.isArray(attach) ? attach : [attach];
                this.wrap.attach_array = [];
                for (var i = 0; i < attach_array.length; i++) {
                    // 编辑前setValue4Write(),不能让oldvalue跟getValue是同一个对象
                    this.wrap.attach_array.push(attach_array[i]);
                    var obj = {};
                    this.wrap.files.push(obj);
                }
                this.showViewList();
                this.wrap.files.length = 0;
            }
            // 按delete或者backspace时候
            if (attach == '') {
                this.reset();
            }
        },

        /**
         * 生成上传文件列表
         * @param {JSON} attach 上传的文件信息对象
         * @param {Number} i 位置索引
         * @returns {jQuery} 返回生成的列表DOM
         */
        createListItem: function (attach, i) {
            var self = this;
            var download = $("<li></li>");
            var cancelButton;
            download
                .append(cancelButton = ($("<a class='fr-fileupload-progressCancel' href='#'> </a>"))
                    .click(function (e) {
                        self.removeAttach(attach, download);
                        e.stopEvent();
                    }).hide())
                .append($("<span class='fr-fileupload-fileNameItem'>"
                    + self.wrap.attach_names[i] + " "
                    + FR.__fileSizeFormat__(attach.fileSize) + "</span>")
                    .bind("click", function () {
                        var attach_id = attach.attach_id;
                        window.open(FR.servletURL
                            + "?op=fr_attach&cmd=ah_download&id="
                            + attach_id);
                    })
                    .mouseover(function () {
                        $(this).css({color: 'blue' })
                    })
                    .mouseout(function () {
                        $(this).css({color: '' })
                    })).addClass("fr-fileupload-listitem").mouseover(
                function () {
                    cancelButton.show();
                    $(this).css({'background-color': '#9FC5F8'})
                }).mouseout(function () {
                    cancelButton.hide();
                    $(this).css({'background-color': ''})
                });
            self.wrap.attachNum++;
            if (self.wrap.maxlength !== 1) {
                self.$previewCount.text(self.wrap.attachNum);
            }

            return download;
        },

        /**
         * 显示文件列表
         */
        showViewList: function () {
            var self = this;
            var fileListDiv;
            var fileListWrap;
            if (!self.options.hideFileList) {
                var fileListUl = $("ul", self.element);
                if (fileListUl.length === 0) {
                    var contentDiv = $("<div class='fr-fileupload-popview'/>").appendTo(self.element).css({
                        marginTop:  18 - self.options.height / 2,
                        marginLeft : self.options.width / 2 + 18
                    });
                    fileListDiv = $("<div class='fr-fileupload-popview-list'/>").appendTo(contentDiv);
                    fileListWrap = $("<ul/>").addClass("fr-fileupload-list").appendTo(fileListDiv);
                } else {
                    fileListDiv = fileListUl.parent();
                    fileListWrap = fileListUl;
                }
            }
            var wrap = self.wrap;
            this.imageURL = null;
            if (self.options.maxlength === 1) {
                var o = this.options;
                var attach = wrap.attach_array[0];
                this.removeBackground();

                if (attach.attach_type == 'image') {
                    self.$tempPreview =
                        $("<td></td>")
                            .appendTo(this.divWrap).css({
                                left: self.element.outerWidth(true) - self.element.width(),
                                width: o.width,
                                height: o.height,
                                top: 0,
                                position: 'absolute'
                            });
                    FR.lastTarget = self.$tempPreview;
                    var $target = $(self.$tempPreview);
                    $target.css("background", "");
                    var im_url = FR.servletURL + '?op=fr_attach&cmd=ah_image&id='
                        + attach.attach_id;
                    $target.css('background', 'url(' + im_url + ") 0 0 no-repeat transparent");
                    this.imageURL = im_url;
                    $target.css("cursor", "default").unbind("click", download)
                }
                wrap.attach_names[0] = attach.filename;
                if (fileListWrap) {
                    fileListWrap.children().remove();
                    fileListWrap.append(this.createListItem(attach, 0));
                }
            }
            // 多文件时要处理重名的问题
            if (self.options.maxlength !== 1) {
                for (var i = wrap.attach_array.length - 1, m = 0; m < wrap.files.length; i--, m++) {
                    wrap.attach_names[i] = wrap.attach_array[i].filename;
                    var dup = 0;
                    for (var j = 0; j < wrap.attach_array.length - wrap.files.length; j++) {
                        if (wrap.attach_names[i] === wrap.attach_array[j].filename) {
                            dup++;
                        }
                    }
                    if (dup > 0) {
                        wrap.attach_names[i] = FR.lengthenFileName(wrap.attach_array[i].filename, "(" + dup + ")");
                    }
                    fileListWrap && fileListWrap.append(this.createListItem(wrap.attach_array[i], i));
                }
            }
            // ie杂项不支持max-height属性
            if (FR.Browser.isIE() && fileListDiv) {
                if (fileListDiv.height() > 160) {
                    fileListDiv.height(160);
                    if (fileListWrap.width() + 18 > fileListDiv.width()) {
                        fileListDiv.width(fileListWrap.width() + 18);
                    }
                }
            }
            function download(e) {
                window.open(FR.servletURL + "?op=fr_attach&cmd=ah_download&id="
                    + e.data);
                e.stopPropagation();
            }
        },

        /**
         * 移除已上传的文件
         * @param {JSON} attach 上传的文件对象
         * @param {jQuery} download 文件显示所在的DOM对象
         */
        removeAttach: function (attach, download) {
            var attach_id = attach.attach_id;
            var self = this;
            var wrap = this.wrap;
            FR.ajax({
                url: FR.servletURL + "?op=fr_attach&cmd=ah_release",
                data: {
                    id: attach_id
                },
                complete: function (res, status) {
                    if (status == 'success') {
                        if (download) {
                            download.remove();
                        }
                        for (var n = 0; n < wrap.attach_array.length; n++) {
                            if (wrap.attach_array[n].attach_id == attach_id) {
                                if (self.wrap.maxlength !== 1) {
                                    wrap.attachNum--;
                                    self.$previewCount.text(self.wrap.attachNum);
                                    if (wrap.attachNum === 0) {
                                        $(".fr-fileupload-popview", self.element).remove();
                                    }
                                }
                                wrap.attach_array.remove(wrap.attach_array[n]);
                                break;
                            }
                        }
                        if (self.wrap.maxlength === 1) {
                            $(".fr-fileupload-popview", self.element).remove();
                            self.removeBackground();
                        }
                        self.fireEvent(FR.Events.CALLBACK);
                    }
                }
            })
        },

        /**
         * 重置背景图片
         * 格子的高度可能发生了改变 要调整
         * @param u
         */
        resetBackground: function(u) {
            var url = u || this.imageURL;
            this.removeBackground();
            if (this.options.tdCell) {
                this.options.tdCell.css('background', 'url(' + url
                    + "&height=" + this.options.tdCell.height() + ") 0 0 no-repeat transparent");
            }
        },

        /**
         * 特指移除单文件上传中添加图片后的背景
         */
        removeBackground: function () {
            // 这个background是指单文件添加了图片的情况
            // 有两处需要移除 一个原始报表结构的td中 一个是动态生成的x-editor中
            // 还有可能用在表单啊
            if (this.options.tdCell) {
                this.options.tdCell.css('background-image', '');
            }
            var previousAtt = this.divWrap.children().eq(2);
            previousAtt.css('background-image', '');
            previousAtt.remove();
        },


        startEditing: function () {
            if (this.options.tdCell) {
                $('.attach-download-div,.fr-fileupload-download-all', $(this.options.tdCell)).hide();
            }
            this.$preview.show();
            // richer:文件的enable需要单独处理
            if (this.options.disabled) {
                this.$preview.unbind("click");
            }
            // IE杂项模式 x-editor的高度总是比文件控件高一些 导致浅蓝色边框超出
            // 没搞懂为什么变大 索性去掉这个控件编辑的浅蓝框子
            if (FR.Browser.isIE() && !$.support.boxModel && this.options.write) {
                $(".x-editor").addClass('none-border');
            }
        },

        stopEditing: function () {
            if (this.options.tdCell) {
                var cur = $('.attach-download-div,.fr-fileupload-download-all', $(this.options.tdCell));
                cur.show();
            }
            if (FR.Browser.isIE() && !$.support.boxModel && this.options.write) {
                $(".x-editor").removeClass('none-border');
            }
            if (this.imageURL != null) {
                var self = this;
                setTimeout(function() {
                    self.resetBackground();
                }, 200);
            }
        },

        getValue: function () {
            if (!this.wrap.attach_array) {
                //return [];
                // shoc: 返回空数组有个问题,提交入库的时候空文件控件值到后台变成"[]"始终会入库一条记录,
                // 后台拦截了null、""等情况,在那里判断拦截这个不太合适,还是改这里了
                return "";
            }
            if (this.options.maxlength === 1 && this.wrap.attach_array[0]
                && this.wrap.attach_array[0].attach_type == "image") {
                return this.wrap.attach_array[0];
            }
            return this.wrap.attach_array.length === 0 ? "" : this.wrap.attach_array;
        },

        setEnable: function (enable) {
            FR.MultiFileEditor.superclass.setEnable.apply(this, arguments);
            if (this.$fileupload && this.$fileupload[0]) {
                if (enable) {
                    this.$fileupload[0].removeAttribute("disabled");
                } else {
                    this.$fileupload[0].setAttribute("disabled", "disabled");
                }
            }
        },

        /**
         * 是否显示预览图片
         * @returns {Boolean} 返回是否显示预览图片
         */
        isShowViewImage: function () {
            return this.options.showViewImage && this.options.maxlength === 1;
        },

        reset: function () {
            this.wrap.attach_array = [];
            this.wrap.attach_names = [];
            this.wrap.attachNum = 0;
            if (this.options.tdCell) {
                $('.attach-download-div', $(this.options.tdCell)).remove();
            }
            $('.fr-fileupload-popview', this.element).remove();
            this.removeBackground();
        }
    });
    $.shortcut("multifile", FR.MultiFileEditor);
})(jQuery);