;
(function ($) {
    /**
     * 数字控件
     *
     *     @example
     *     var editor = new FR.NumberEditor({
     *          renderEl : 'body',
     *          allowDecimals : true,
     *          allowNegative : true,
     *          decimalPrecision : -1,
     *          autoVerify : true,
     *          decimalSeparator : ".",
     *          value : -233.455
     *     });
     *
     * @class FR.NumberEditor
     * @extends FR.EditComp
     * @cfg {JSON} options 属性配置
     * @cfg {Boolean} [options.allowDecimals=true] 是否允许小数
     * @cfg {Boolean} [options.allowNegative=true] 是否允许负数
     * @cfg {Number} [options.decimalPrecision=-1] 小数精确度
     * @cfg {String} [options.decimalSeparator=.] 小数分割符
     */
    FR.NumberEditor = FR.extend(FR.EditComp, /**@class FR.NumberEditor*/{
        _defaultConfig: function () {
            return $.extend(FR.NumberEditor.superclass._defaultConfig.apply(), {
                allowDecimals: true,
                allowNegative: true,
                decimalPrecision: -1,
                autoVerify: true,
                decimalSeparator: '.'// decimal的分隔符
                // alex:不添加value:0作为默认值,这样会导致在BS编辑的时候,如果写的是0,发现isDirty ==
                // false,而不赋值
            });
        },
        _init: function () {
            FR.NumberEditor.superclass._init.apply(this, arguments);
            var o = this.options;
            var baseChars = '0123456789';

            this.allowed = baseChars + '';
            if (o.allowDecimals) {
                this.allowed += '.';
            }
            if (o.allowNegative) {
                this.allowed += "-";
            }
            // b:屏蔽输入法
            this.editComp.css("ime-mode", "disabled");
            var self = this;
            this.editComp.blur(function () {
                if ('.' == self.editComp.val().charAt(0)) {
                    self.editComp.val('0' + self.editComp.val());
                }
            }).keydown(function (e) {
                    // wei : 不触发参数界面查询按钮
                    if (e.keyCode == FR.keyCode.ENTER && !self.options.write) {
                        e.stopPropagation();
                    }
                }).keypress(function (e) {
                    // james:下面是抄的Ext的
                    var k = e.keyCode;
                    if (!$.browser.msie
                        && (FR.isNavKeyPress(e) || FR.isSpecialKey(e) || k == FR.keyCode.BACKSPACE)) {
                        return;
                    }
                    var c = e.charCode || e.keyCode;// james:IE当中要取keyCode
                    var cc = String.fromCharCode(c);
                    // if($.browser.msie && (FR.isSpecialKey(e) || !cc)){
                    // 过滤掉回车(ASCII为13)和ESC(ASCII为27)
                    if ($.browser.msie && (c === 27 || c === 13)) {
                        return;
                    }

                    if (self.allowed.indexOf(cc) === -1) {
                        // FR.Msg.toast(errorMsg);
                        e.preventDefault();
                    }

                    if (this.value.indexOf('.') > -1 && cc == '.') {
                        // FR.Msg.toast(errorMsg);
                        e.preventDefault();
                    }
                });
        },

        isValidateInput: function (e) {
            var c = e.charCode || e.keyCode;// james:IE当中要取keyCode
            // wei:backspace
            if (c == FR.keyCode.BACKSPACE || c == FR.keyCode.ENTER) {
                return true;
            }
            // 上面数字键盘是48-57 数字小键盘是96-105 同样小数点也要考虑两个
            if (c >= 96 && c <= 105) {
                c = c - 48;
            }
            var cc = String.fromCharCode(c);
            if (c === 190 || c === 110) {
                cc = ".";
            }
            return (this.allowed.indexOf(cc) > -1)
                && (cc != '.' || (this.editComp.val().substr(0, this.editComp.val().length - 1)).indexOf('.') === -1);
        },

        _dealValueWithEvents: function (value) {
            var oldValue = this.getValue();
            var txt;
            if (typeof oldValue == 'string' && oldValue != '') {
                txt = oldValue;
            } else {
               // value = parseFloat(value);
                txt = String(value);
            }

            this.editComp.val( txt.replace(".",
                this.options.decimalSeparator));

            // alex:把老的值保存在this.options.value中,用来判断isDirty
            if (arguments[1] !== false) {
                this.fireEvent(FR.Events.CHANGE, value, oldValue); // fire value
                // change event,
                // newValue &
                // oldValue
            }
        },

        _fixPrecision: function (value) {
            var nan = isNaN(value);
            if (!this.options.allowDecimals || this.options.decimalPrecision == -1
                || nan || !value) {
                return nan ? '' : value;
            }
            return parseFloat(parseFloat(value).toFixed(this.options.decimalPrecision));
        },

        // float只能支持到17位,而21位才开始转化成科学计数法,
        // 17到21位会出错,21位以上位数正常但是会舍掉一部分  todo
        _parseValue: function (value) {
            value = parseFloat(String(value).replace(this.options.decimalSeparator, "."));
            return isNaN(value) ? '' : value;
        },
        // james:对于数字编辑器的返回值,如果没有值,就返回'',如果输入的是0,就返回0
        // 这个地方要看用户的反馈,是否需要提供可配置的地方。
        getValue: function () {
            var txt = this.editComp.val();
            if (txt.length > 17) {
                return txt;
            }
            return this._fixPrecision(this._parseValue(txt));
        },

        verifyDedimals: function () {
            if (typeof this.editComp.reg == "undefined") {
                this.editComp.reg = (this.options.allowNegative ? "\-?" : "")
                    + "\\d+"
                    + (this.options.allowDecimals ? ("(\\.\\d{0,"
                    + this.options.maxDecLength + "})?") : "");
            }
            var pattern = new RegExp(this.editComp.reg);
            var result = pattern.exec(this.editComp.val());
            if (result != null) {
                return result[0];
            }
            return "";
        },

        recoveryValue: function () {
            this.editComp.val(isNaN(this.options.oldValue)
                ? ''
                : String(this.options.oldValue).replace(".",
                this.options.decimalSeparator));
        },

        isValidate: function (cValue) {
            var value = cValue != null && cValue != undefined
                ? cValue
                : this.editComp.val();
            if(cValue && this.options.isEditable && (''+ cValue).indexOf(',') != -1){
                value = value.replace(/,/g, "");
            }
            // richer:不允许为空
            // b: 不确定这么改有没有问题
            // value==""时如果value=0则表达式为ture,放在最后安全
            if (value == null || value == undefined || value === "") {
                if (this.options.allowBlank !== false) {
                    return true;
                } else {
                    this.errorMsg = this.options.errorMsg || FR.i18nText("FR-Base_NOT_NULL_Des");
                    return false;
                }
            }

            value = ('' + value).replace(this.options.decimalSeparator, ".");
            if (isNaN(value)) {
                this.errorMsg = this.options.errorMsg
                    || FR.i18nText("Err-The_value_must_be_number");
                return false;
            }
            // 不允许为小数

            // 数字太大parseFloat就变成科学计数法的形式了 而且总位数17以上的小数会被截断
            var str = value;
            var bd = new FR.BigDecimal({
                numStr: str
            });
            if (str.indexOf(this.options.decimalSeparator) > 0) {
                if (!this.options.allowDecimals) {
                    this.errorMsg = this.options.errorMsg
                        || FR.i18nText("Err-The_value_must_be_integer");
                    return false;
                } else {
                    if (str.length - str.indexOf(this.options.decimalSeparator) > this.options.maxDecLength + 1) {
                        this.errorMsg = this.options.errorMsg
                            || FR.i18nText("FR-Base_DecimalNumber_Out");
                        return false;
                    }
                }
            }
            // 不允许为负数
            if (!this.options.allowNegative && !bd.isPositive()) {
                this.errorMsg = this.options.errorMsg
                    || FR.i18nText("FR-Report_Invalid_Cell");
                return false;
            }
            if (this.options.minValue != null &&
                bd.lessThan(new FR.BigDecimal({numStr: String(this.options.minValue)}))) {
                this.errorMsg = this.options.errorMsg
                    || FR.i18nText("Err-The_number_is_less_than_the_minimum_value")
                    + this.options.minValue;
                return false;
            }
            if (this.options.maxValue != null &&
                bd.greaterThan(new FR.BigDecimal({numStr: String(this.options.maxValue)}))) {
                this.errorMsg = this.options.errorMsg
                    || FR.i18nText("Err-The_number_is_larger_than_the_maximum_value")
                    + this.options.maxValue;
                return false;
            }
            return true;
        },

        doResize: function (give) {
            FR.NumberEditor.superclass.doResize.call(this, give);
        }
    });
    $.shortcut("number", FR.NumberEditor);

    /**
     * 双精度数处理函数
     * @param {JSON} config 配置属性
     * @constructor
     */
    FR.BigDecimal = function (config) {
        this.options = $.extend({
            numStr: '',
            decimalSeparator: '.'
        }, config);
        var o = this.options;
        var str = o.numStr;
        // 正数
        this.positive = true;
        // 整数部分
        this.intArray = [];
        // 小数部分
        this.decArray = [];

        //
        if (str.indexOf("e") !== -1 || str.indexOf("E") !== -1) {

        }
        var i=0;
        var dealPos = true;
        if (str.charAt(0).match(/[-+]/)) {
            this.positive = str.charAt(0) == '+';
            i ++;
        }
        for (; i<str.length; i++) {
            var c = str.charAt(i);
            if (c == o.decimalSeparator) {
                dealPos = false;
                continue;
            }
            if (dealPos) {
                this.intArray.push(c);
            } else {
                this.decArray.push(c);
            }
        }
    };
    $.extend(FR.BigDecimal.prototype, {
        isPositive: function() {
            return this.positive;
        },

        equalsTo: function(bigDecimal) {
            return this.compareTo(bigDecimal) === 0;
        },

        greaterThan: function(bigDecimal) {
            return this.compareTo(bigDecimal) === 1;
        },

        lessThan: function(bigDecimal) {
            return this.compareTo(bigDecimal) === -1;
        },

        compareTo: function(bigDecimal) {
            if (bigDecimal == null) {
                return null;
            }
            if (this.isPositive() && !bigDecimal.isPositive()) {
                return 1;
            }
            if (!this.isPositive() && bigDecimal.isPositive()) {
                return -1;
            }
            var res = 0;
            var arr = this.intArray;
            if (arr.length > bigDecimal.intArray.length) {
                res = 1;
            } else if (arr.length < bigDecimal.intArray.length) {
                res = -1;
            } else {
                for (var i=0; i<arr.length; i++) {
                    if (arr[i] > bigDecimal.intArray[i]) {
                        res = 1;
                        break;
                    } else if (arr[i] < bigDecimal.intArray[i]) {
                        res = -1;
                        break;
                    }
                }
                if (res === 0) {
                    var decArr = this.decArray;
                    var decLen = Math.min(decArr.length, bigDecimal.decArray.length);
                    for (var j= 0; j<decLen; j++) {
                        if (decArr[j] > bigDecimal.decArray[j]) {
                            res = 1;
                            break;
                        } else if (decArr[j] < bigDecimal.decArray[j]) {
                            res = -1;
                            break;
                        }
                    }
                    if (res === 0) {
                        if (decArr[decLen] != null) {
                            res = 1;
                        } else if (bigDecimal.decArray[decLen] != null) {
                            res = -1;
                        }
                    }
                }
            }
            return this.isPositive() ? res : -res;
        }
    });
})(jQuery);