(function () {
    /**
     * 基本的编辑器父类,这是一个抽象类
     * @class FR.BaseEditor
     * @extends FR.Widget
     * @abstract
     */
    FR.BaseEditor = FR.extend(FR.Widget, {
        /**
         * 判断是否支持数据绑定
         * @returns {Boolean} 支持数据绑定则返回true,否则返回false
         */
        isSupportDatabinding: function () {
            return true;
        },

        /**
         * 加载数据
         */
        loadData: function () {
            if (this.options.widgetName) {
                var value = this.options.form.formData[this.options.widgetName];
                if (value) {
                    this.setValue(value, false);
                }
            }
        },
        /**
         * 保存数据绑定的数据
         */
        store: function () {
            if (this.options.Databinding) {
                var name = this.options.Databinding.Name;
                var key = this.options.Databinding.Key;
                if (name && key) {
                    var value = this.getValue();
                    var state = this.options.form.formData.setValue(name,
                        key, value);
                }
            }
        },
        getValue: function () {
        },

        setValue: function (value) {
            // wei : setValue的时候不提示是否输错,在stopCellEditing的时候再提示。
            if (!this.isValidate(value)) {
                return false;
            }
            if ((value || value === 0) && this.options.watermark) {
                this.clearWaterMark();
            }
            if (arguments[1] != undefined) {
                this._dealValueWithEvents(value, arguments[1]);
            } else {
                this._dealValueWithEvents(value, false);
            }
        },

        _dealValueWithEvents: function (value, shouldFireEvent) {
        },
        dealWithDisplayValue: function (showValue) {
        },

        getText: function () {
            return this.getValue();
        },

        setText: function (val) {
            this.setValue(val);
        },

        clearWaterMark: function () {
        },

        /**
         * 获取错误提示内容
         * @returns {String} 返回错误提示内容
         */
        getErrorMsg: function () {
            return this.errorMsg;
        },

        /**
         * 校验并且设置状态标志
         * @param {String} cValue 被校验的值
         */
        checkValid: function (cValue) {
            if (this.isValidate(cValue)) {
                this.validateCss();
                return true;
            } else {
                this.invalidateCss();
                return false;
            }
        },

        /**
         * 校验值是否符合控件的值规范
         * 这个方法只做两件事:判断是否符合规范;如果不符合的话设置this.errorMsg
         * 不要在这个方法里设置控件的CSS样式
         * @param cValue  将要给控件赋的值
         * @returns {boolean} 符合控件的校验要求则返回true,否则返回false
         */
        isValidate: function (cValue) {
            var allowBlank = this.options.allowBlank !== false;
            /* daniel: value为0时 value=false*/
            var value = cValue != null && cValue != undefined
                ? cValue
                : this.getValue();
            var regex = this.options.regex;
            /* daniel: 不要使用value ==""判断空 ""==0*/
            // value为null也要加上
            if (value == null || value === "" || FR.isEmptyArray(value)) {
                if (allowBlank) {
                    return true;
                } else if (FR.equals("illegalvalue", value)) {
                    this.errorMsg = this.options.errorMsg
                        || FR.i18nText("FR-Engine-Not_In_List");
                    return false;
                } else {
                    this.errorMsg = this.options.errorMsg
                        || FR.i18nText("FR-Base_NOT_NULL_Des");
                    return false;
                }
            }

            if (regex) {
                for (var i = 0, len = FR.BaseEditor.PluginRegex.length; i < len; i++) {
                    var obj = FR.BaseEditor.PluginRegex[i];
                    if (obj.text === regex) {
                        if (obj.regex(value)) {
                            return true;
                        } else {
                            this.errorMsg = FR.i18nText("FR-Base_Error_Input_Value");
                            return false;
                        }
                    }
                }

                if (typeof regex == 'string') {/* String的时候,构造一个RegExp出来*/
                    try {
                        regex = new RegExp(regex);
                    } catch (err) {
                        this.errorMsg = "invalid Regular expressions";
                        return false;
                    }
                }
                if (!regex.test(value)) {
                    /* 正则表达式是判断长度的 换行符算两个字符*/
                    if (!(regex.source.indexOf(".{") > -1 && regex.test(value.replace(/\n/g, "aa")))) {
                        this.errorMsg = FR.i18nText("FR-Base_Error_Input_Value");
                        return false;
                    }
                }
            }

            return true;
        },

        /**
         * 初始化数据
         * @protected
         */
        initData: function () {
            if (this.options.data) {
                return;
            }
            if (this.options.widgetUrl) {
                this.options.data = FR.DataFactory
                    .createJSONData(this.options.widgetUrl, this.options);
            } else if (this.options.items) {
                this.options.data = FR.DataFactory
                    .createArrayData(this.options.items, this.options);
            }
        },

        /**
         * 数据联动,获取联动数据
         * @returns {Object}
         */
        getDependenceObj: function () {
            var o = this.options;
            /* carl两手准备,参数界面上是没有扩展的,所以依据dependence来弄。*/
            /* 报表主体上有扩展,就需要dependenceMap的映射来得知应该拿扩展后的哪个格子*/
            var depO = {};
            if (o.dependenceMap) {
                var self = this;
                $.each(o.dependenceMap, function (key, item) {
                    if (self.options.form) {
                        /* richer:同FR.FORM中一致,不区分参数名的大小写*/
                        var val = self.options.form
                            .resolveVariable(item);
                        if (val != "FR.primitive" && val != null) {
                            depO[key.toUpperCase()] = val;
                        }
                    } else if (self.options.write) {
                        /* richer:填报状态的联动*/
                        item = item.startWith("$") ? item.substring(1) : item;
                        var checkValue;
                        if (contentPane.curLGP.write) {
                            var depWidget = contentPane.curLGP.write.getWidgetByCell(item)
                                || contentPane.curLGP.write.getWidgetByName(item);
                            if (depWidget) {
                                checkValue = depWidget.getValue();
                            }
                        }
                        if (checkValue == undefined) {
                            /* marro:如果参数是单元格,并且单元格没控件,就把单元格值传过去。*/
                            var col = FR.cellStr2ColumnRow(item);
                            if (col) {
                                var tdCell = contentPane.curLGP
                                    .getTDCell(col);
                                if (tdCell) {
                                    checkValue = FR
                                        .getCellValue(tdCell);
                                }
                            }
                        }
                        if (checkValue != "FR.primitive" && checkValue != null && checkValue != undefined && checkValue != "") {
                            depO[key.toUpperCase()] = checkValue;
                        }
                    }
                });
            } else if (FR.isArray(o.dependence)) {
                for (var idx = 0; idx < o.dependence.length; idx++) {
                    var dep = o.dependence[idx];
                    if (this.options.form) {
                        /* richer:同FR.FORM中一致,不区分参数名的大小写*/
                        var val = this.options.form.resolveVariable(dep);
                        if (val != "FR.primitive" && val != null) {
                            depO[dep.toUpperCase()] = val;
                        }
                    } else if (this.options.write) {
                        /* richer:填报状态的联动*/
                        dep = dep.startWith("$") ? dep.substring(1) : dep;
                        var checkValue;
                        if (contentPane.curLGP.write) {
                            var depWidget = contentPane.curLGP.write
                                    .getWidgetByCell(dep)
                                || contentPane.curLGP.write
                                    .getWidgetByName(dep);
                            if (depWidget) {
                                checkValue = depWidget.getValue();
                            }
                        }
                        if (!checkValue) {
                            /* marro:如果参数是单元格,并且单元格没控件,就把单元格值传过去。*/
                            var col = FR.cellStr2ColumnRow(dep);
                            if (col) {
                                var tdCell = contentPane.curLGP
                                    .getTDCell(col);
                                if (tdCell) {
                                    checkValue = FR.getCellValue(tdCell);
                                }
                            }
                        }
                        if (checkValue != "FR.primitive"
                            && checkValue != null) {
                            depO[dep.toUpperCase()] = checkValue;
                        }
                    }
                }
            }
            return depO;
        },

        /**
         * 数据联动,生成参数依赖
         * @returns {Object} 依赖的参数
         */
        createDependencePara4Data: function () {
            return {
                parameter: {
                    dependence: this.getDependenceObj()
                }
            }
        },

        reset: function () {
            this.setValue("");
        }
    });

    /**
     * 正则表达式控件插件接口
     * @type {Array} 正则表达式类型数组
     */
    FR.BaseEditor.PluginRegex = [];

    /**
     * 带有EditComp的控件父类
     * 包括FR.TriggerEditor  FR.EditComp
     * @class FR.EditCompBaseEditor
     * @extends FR.BaseEditor
     */
    FR.EditCompBaseEditor = FR.extend(FR.BaseEditor, {

        _defaultConfig: function () {
            return $.extend(FR.EditCompBaseEditor.superclass._defaultConfig.apply(), {});
        },

        /**
         * 设置水印
         * @param text 水印内容
         */
        setWaterMark: function (text) {
            if (text == undefined) {
                text = this.options.watermark;
            }
            FR.$defaultImport('/com/fr/web/core/js/jquery.watermark.js', 'js');
            this.editComp.watermark(text, this.options.isEditable);
        },
        /**
         * 移除水印
         */
        removeWaterMark: function () {
            FR.$defaultImport('/com/fr/web/core/js/jquery.watermark.js', 'js');
            this.editComp.watermark({
                remove: true
            });
        },
        /**
         * 清空水印
         */
        clearWaterMark: function () {
            FR.$defaultImport('/com/fr/web/core/js/jquery.watermark.js', 'js');
            this.editComp.watermark({
                clear: true
            });
        },

        /**
         * 移除不符合规则的提示样式
         */
        validateCss: function () {
            this.editComp.removeClass('fr-invalid');
            this.editComp.removeAttr('title');
        },

        /**
         * 显示不符合规则的提示样式
         */
        invalidateCss: function () {
            this.editComp.addClass('fr-invalid');
            this.editComp.attr('title', this.getErrorMsg());
        }
    });

    /**
     * 这是一个抽象类,文本(域)/密码控件和数字控件的父类,不能直接使用。
     * @class FR.EditComp
     * @extends FR.BaseEditor
     * @abstract
     *
     * @cfg {JSON} options 属性配置
     * @cfg {String} options.cls 样式类
     * @cfg {String} options.id 唯一标识符
     * @cfg {Number} options.fontSize 字体大小
     * @cfg {String} options.text 控件的显示值
     * @cfg {String} options.value 控件的实际值
     * @cfg {Boolean} [options.disabled=false] 控件是否不可用
     * @cfg {Object} [options.watermark=false] 是否有水印,水印内容
     * @cfg {String} options.style 其他自定义样式
     * @cfg {Boolean} [options.allowBlank=true] 是否允许为空
     * @cfg {String} options.regex 填写规则
     * @cfg {Boolean} [options.autoVerify=false] 是否开启实时校验
     * @cfg {String} options.errorMsg 不符合填写规则的时候的报错信息
     */
    FR.EditComp = FR.extend(FR.EditCompBaseEditor, /**@class FR.EditComp*/{
        /**
         * 初始的属性配置
         * @returns {*}
         * @private
         */
        _defaultConfig: function () {
            return $.extend(FR.EditComp.superclass._defaultConfig.apply(), {
                cls: 'fr-texteditor',
                width: 120,
                height: 22,
                autoVerify: false
            });
        },
        /**
         * 初始化控件
         * @private
         */
        _init: function () {
            FR.EditComp.superclass._init.apply(this, arguments);
            var self = this;
            var o = this.options;
            this.editComp = this._createEditComp();
            if (FR.Browser.isIE()) {
                this.editComp.on('paste', function () {
                    var str = window.clipboardData.getData("Text");
                    str = str.replace(/\s|\n/g, " "); // replace space or newline
                    //bug79391,复制的时候有原值的话不能直接覆盖
                    this.value = this.value ? this.value.append(str) : str;
                    return false;
                });
            }
            this.editComp.appendTo(this.element);
            if (o.fontSize) {
                this.editComp.css('font-size', o.fontSize);
            }
            this.validateCss();

            this.editComp.attr("name", o.widgetName).addClass(o.cls);
            if (FR.Browser.isIE8()) {
                this.editComp.css('margin-top', 0);
            }

            if (o.text) {
                this.editComp.attr("value", o.text);
            }
            if (o.id) {
                this.editComp.attr('id', o.id);
            }
            if (o.disabled === true) {
                this.editComp.attr("disabled", "disabled");
            }
            o.width = (o.width > -1) ? o.width : 120;
            o.height = (o.height > -1) ? o.height : 22;
            this.doResize(o);
            //若有style属性,则添加自定义的样式
            FR.applyStyles(this.editComp, o.style);
            this.editComp.focus(function (e) {// 获得焦点的事件
                self.editComp.addClass(o.cls + '-focus');
                if (!self.options.write) {
                    self.fireEvent(FR.Events.BEFOREEDIT);
                }
            }).blur(function (e) {// 失去焦点的事件
                self.editComp.removeClass(o.cls + '-focus');
                //Sean: options.write为true表示是填报
                if (!self.options.write) {
                    self.checkValid();
                    self.fireEvent(FR.Events.STOPEDIT);
                }
            }).keyup(function (e) {
                if (o.autoVerify) {
                    self.checkValid();
                }
                if (self.isValidateInput(e)) {
                    self.fireEvent(FR.Events.AFTEREDIT, e);
                }
            });
            this.errorMsg = this.options.errorMsg || '';// james:ERROR Message要记下来
            if (o.value != null) {
                this.setValue(o.value, false);
            }
        },
        _createEditComp: function () {
            return $("<input type='text'/>");
        },

        doResize: function (give) {
            FR.EditComp.superclass.doResize.call(this, give);
            this.element.css({
                width: give.width,
                height: give.height
            });

            this.editComp.css("width", $.support.boxModel ? give.width - 8 : give.width);
            this.editComp.css("height", $.support.boxModel ? give.height - 4 : give.height); // alex:去掉上下边框的高度
            //Sean: 水印的生成随resize一起,因为水印字体的大小要适应控件的输入框大小
            if (give.watermark) {
                this.removeWaterMark();
                this.setWaterMark();
            }

        },

        setEnable: function (arg) {
            FR.EditComp.superclass.setEnable.apply(this, arguments);
            if (this.editComp) {
                // 如果是填报初始化控件时还没有editComp.
                if (arg === true) {
                    this.editComp.removeAttr("disabled");
                } else if (arg === false) {
                    this.editComp.attr("disabled", "disabled")
                }
            }
        },

        /**
         * 选取控件中的文本内容
         * @param start 起始字符位置,默认为0
         * @param end 结束字符位置,默认为文本长度
         */
        selectText: function (start, end) {
            if (!this.editComp.is(":visible")) {
                // 这里不能保证editComp肯定是可见的。如果不可见下面的方法就会报错
                return;
            }
            // james:抄的Ext的
            var cv = this.editComp.val();
            if (cv && cv.length > 0) {
                start = start === undefined ? 0 : start;
                end = end === undefined ? cv.length : end;
                var d = this.editComp[0];
                if (d.setSelectionRange) {
                    d.setSelectionRange(start, end);
                } else if (d.createTextRange) {
                    var range = d.createTextRange();
                    range.moveStart("character", start);
                    range.moveEnd("character", end - cv.length);
                    range.select();
                }
            }
        }
    });
})(jQuery);