import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _get from "@babel/runtime/helpers/get";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _createSuper from "@babel/runtime/helpers/createSuper";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import { __decorate } from "tslib";
import React, { isValidElement } from 'react';
import { action, computed, isArrayLike, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import isString from 'lodash/isString';
import isPlainObject from 'lodash/isPlainObject';
import defaultTo from 'lodash/defaultTo';
import isNil from 'lodash/isNil';
import { BigNumber } from 'bignumber.js';
import { math } from 'choerodon-ui/dataset';
import KeyCode from '../../../es/_util/KeyCode';
import { TextField } from '../text-field/TextField';
import autobind from '../_util/autobind';
import keepRunning from '../_util/keepRunning';
import Icon from '../icon';
import { getNearStepValues, parseNumber } from './utils';
import isEmpty from '../_util/isEmpty';
import { $l } from '../locale-context';
import { FieldType } from '../data-set/enum';
import defaultFormatNumber from '../formatter/formatNumber';
import localeContext from '../locale-context/LocaleContext';
import { getNumberFormatOptions, getNumberFormatter } from '../field/utils';

function getCurrentValidValue(value, options) {
  var valueBig = new BigNumber(value.replace(/\.$/, ''));
  return math.isValidBigNumber(valueBig) ? options.strict ? valueBig : math.fix(valueBig) : 0;
}

function getStepUpGenerator() {
  return this.stepGenerator(true);
}

function getStepDownGenerator() {
  return this.stepGenerator(false);
}

function run(value) {
  var element = this.element;

  if (element) {
    element.value = String(value);
  }
}

function enabled() {
  return Boolean(this.getProp('step'));
}

var stepUpKeyboardProps = {
  getStepGenerator: getStepUpGenerator,
  run: run,
  validator: function validator(target) {
    return target === this.element;
  },
  enabled: enabled
};
var stepDownKeyboardProps = {
  getStepGenerator: getStepDownGenerator,
  run: run,
  validator: function validator(target) {
    return target === this.element;
  },
  enabled: enabled
};
var stepUpMouseProps = {
  getStepGenerator: getStepUpGenerator,
  run: run,
  validator: function validator(target) {
    return target === this.plusElement;
  }
};
var stepDownMouseProps = {
  getStepGenerator: getStepDownGenerator,
  run: run,
  validator: function validator(target) {
    return target === this.minusElement;
  }
};
export var NumberField = /*#__PURE__*/function (_TextField) {
  _inherits(NumberField, _TextField);

  var _super = _createSuper(NumberField);

  function NumberField() {
    _classCallCheck(this, NumberField);

    return _super.apply(this, arguments);
  }

  _createClass(NumberField, [{
    key: "lang",
    get: function get() {
      var lang = this.observableProps.lang;

      if (lang) {
        return lang;
      }

      var dataSet = this.dataSet;

      if (dataSet && dataSet.lang) {
        return dataSet.lang;
      }

      var numberFormatLanguage = localeContext.numberFormatLanguage,
          locale = localeContext.locale;

      if (numberFormatLanguage) {
        return numberFormatLanguage;
      }

      return locale.lang;
    }
  }, {
    key: "defaultValidationMessages",
    get: function get() {
      var label = this.getProp('label');
      return {
        valueMissing: $l('NumberField', label ? 'value_missing' : 'value_missing_no_label', {
          label: label
        })
      };
    }
  }, {
    key: "strict",
    get: function get() {
      var field = this.field;
      return field ? field.get('type', this.record) === FieldType.bigNumber : false;
    }
  }, {
    key: "allowDecimal",
    get: function get() {
      var min = this.min,
          nonStrictStep = this.nonStrictStep;
      var precision = this.getProp('precision');

      if (precision === 0) {
        return false;
      } // 非严格步距下允许输入小数


      if (nonStrictStep) {
        return true;
      }

      var step = this.getProp('step');
      return !step || !math.eq(math.mod(step, 1), 0) || !!min && !math.eq(math.mod(min, 1), 0);
    }
  }, {
    key: "nonStrictStep",
    get: function get() {
      var nonStrictStep = this.getProp('nonStrictStep');

      if (nonStrictStep !== undefined) {
        return nonStrictStep;
      }

      var numberFieldNonStrictStep = this.getContextConfig('numberFieldNonStrictStep');

      if (numberFieldNonStrictStep !== undefined) {
        return numberFieldNonStrictStep;
      }

      return false;
    }
  }, {
    key: "allowNegative",
    get: function get() {
      var min = this.min;
      return isNil(min) || min < 0;
    }
  }, {
    key: "min",
    get: function get() {
      return this.getLimit('min');
    }
  }, {
    key: "max",
    get: function get() {
      return this.getLimit('max');
    }
  }, {
    key: "value",
    get: function get() {
      var value = this.observableProps.value;

      if (isArrayLike(value)) {
        return value;
      }

      var range = this.range;

      if (isArrayLike(range)) {
        if (isPlainObject(value)) {
          var _ref;

          var _range = _slicedToArray(range, 2),
              start = _range[0],
              end = _range[1];

          return _ref = {}, _defineProperty(_ref, start, value[start]), _defineProperty(_ref, end, value[end]), _ref;
        }
      }

      return value;
    },
    set: function set(value) {
      var _this = this;

      runInAction(function () {
        _this.observableProps.value = value;
      });
    }
  }, {
    key: "clearButton",
    get: function get() {
      var step = this.getProp('step');

      if (step) {
        return false;
      }

      return _get(_getPrototypeOf(NumberField.prototype), "clearButton", this);
    }
  }, {
    key: "keyboard",
    get: function get() {
      if ('keyboard' in this.props) {
        return this.props.keyboard;
      }

      return this.getContextConfig('numberFieldKeyboard') !== false;
    }
  }, {
    key: "savePlusRef",
    value: function savePlusRef(ref) {
      this.plusElement = ref;
    }
  }, {
    key: "saveMinusRef",
    value: function saveMinusRef(ref) {
      this.minusElement = ref;
    }
  }, {
    key: "isLowerRange",
    value: function isLowerRange(value1, value2) {
      return math.lt(value1, value2);
    }
  }, {
    key: "getFieldType",
    value: function getFieldType() {
      return FieldType.number;
    }
  }, {
    key: "getLimit",
    value: function getLimit(type) {
      var record = this.record;
      var limit = this.getProp(type);

      if (record && isString(limit)) {
        var num = record.get(limit);

        if (num !== undefined) {
          return num;
        }
      }

      return limit;
    }
  }, {
    key: "getValidatorProp",
    value: function getValidatorProp(key) {
      if (['maxLength', 'minLength'].includes(key)) {
        return;
      }

      switch (key) {
        case 'min':
          return this.min;

        case 'max':
          return this.max;

        case 'nonStrictStep':
          return this.nonStrictStep;

        default:
          return _get(_getPrototypeOf(NumberField.prototype), "getValidatorProp", this).call(this, key);
      }
    }
  }, {
    key: "getInnerSpanButton",
    value: function getInnerSpanButton() {
      var prefixCls = this.prefixCls,
          range = this.range,
          clearButton = this.clearButton;
      var longPressPlus = this.props.longPressPlus;
      var step = this.getProp('step');

      if (step && !range && !this.readOnly && !this.disabled) {
        var plusIconProps = {
          ref: this.savePlusRef,
          key: 'plus',
          className: "".concat(prefixCls, "-plus"),
          onMouseDown: longPressPlus ? this.handlePlus : this.handleOncePlus,
          onTouchStart: this.handleOncePlus
        };
        var minIconProps = {
          ref: this.saveMinusRef,
          key: 'minus',
          className: "".concat(prefixCls, "-minus"),
          onMouseDown: longPressPlus ? this.handleMinus : this.handleOnceMinus,
          onTouchStart: this.handleOnceMinus
        };
        return this.wrapperInnerSpanButton( /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", _extends({}, plusIconProps), /*#__PURE__*/React.createElement(Icon, {
          type: "keyboard_arrow_up"
        })), /*#__PURE__*/React.createElement("div", _extends({}, minIconProps), /*#__PURE__*/React.createElement(Icon, {
          type: "keyboard_arrow_down"
        }))));
      }

      if (clearButton) {
        var right;

        if (this.suffixWidth && this.isSuffixClick) {
          right = defaultTo(this.suffixWidth, 0);
        }

        return this.wrapperInnerSpanButton( /*#__PURE__*/React.createElement(Icon, {
          type: "close",
          onClick: this.handleClearButtonClick,
          onMouseDown: this.handleInnerButtonMouseDown
        }), {
          className: "".concat(prefixCls, "-clear-button"),
          style: {
            right: right
          }
        });
      }
    }
  }, {
    key: "getWrapperClassNames",
    value: function getWrapperClassNames() {
      var prefixCls = this.prefixCls;
      var step = this.getProp('step');
      var suffix = this.getSuffix();
      var button = this.getInnerSpanButton();

      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      return _get(_getPrototypeOf(NumberField.prototype), "getWrapperClassNames", this).call(this, _objectSpread(_defineProperty({}, "".concat(prefixCls, "-step-suffix"), button && /*#__PURE__*/isValidElement(suffix) && step), args));
    }
  }, {
    key: "handleEnterDown",
    value: function handleEnterDown(e) {
      if (this.multiple && this.range && this.text) {
        this.prepareSetValue(this.text);
      }

      _get(_getPrototypeOf(NumberField.prototype), "handleEnterDown", this).call(this, e);

      if (this.multiple && this.range) {
        this.setRangeTarget(0);
        this.beginRange();
      }
    }
  }, {
    key: "handleKeyDown",
    value: function handleKeyDown(e) {
      if (!this.disabled && !this.readOnly && this.keyboard) {
        switch (e.keyCode) {
          case KeyCode.UP:
            this.handleKeyDownUp(e);
            break;

          case KeyCode.DOWN:
            this.handleKeyDownDown(e);
            break;

          default:
        }
      }

      _get(_getPrototypeOf(NumberField.prototype), "handleKeyDown", this).call(this, e);
    }
  }, {
    key: "handleKeyDownUp",
    value: function handleKeyDownUp(value) {
      this.afterStep(value);
    }
  }, {
    key: "handleKeyDownDown",
    value: function handleKeyDownDown(value) {
      this.afterStep(value);
    }
  }, {
    key: "handlePlus",
    value: function handlePlus(value) {
      this.afterStep(value);
    }
  }, {
    key: "handleMinus",
    value: function handleMinus(value) {
      this.afterStep(value);
    }
  }, {
    key: "handleOncePlus",
    value: function handleOncePlus() {
      this.step(true);
    }
  }, {
    key: "handleOnceMinus",
    value: function handleOnceMinus() {
      this.step(false);
    }
  }, {
    key: "getOmitPropsKeys",
    value: function getOmitPropsKeys() {
      return _get(_getPrototypeOf(NumberField.prototype), "getOmitPropsKeys", this).call(this).concat(['nonStrictStep', 'formatter', 'formatterOptions', 'longPressPlus', 'precision', 'numberGrouping', 'maxLength', 'minLength', 'keyboard', 'stringMode']);
    }
  }, {
    key: "getOtherProps",
    value: function getOtherProps() {
      var _this2 = this;

      var otherProps = _get(_getPrototypeOf(NumberField.prototype), "getOtherProps", this).call(this);

      delete otherProps.maxLength;
      otherProps.max = this.max;
      otherProps.min = this.min;

      otherProps.onCompositionEnd = function (e) {
        _this2.lock = false;

        _this2.handleChange(e);
      };

      return otherProps;
    }
  }, {
    key: "getObservableProps",
    value: function getObservableProps(props, context) {
      return _objectSpread(_objectSpread({}, _get(_getPrototypeOf(NumberField.prototype), "getObservableProps", this).call(this, props, context)), {}, {
        max: props.max,
        min: props.min,
        precision: props.precision,
        nonStrictStep: props.nonStrictStep
      });
    }
  }, {
    key: "stepGenerator",
    value: function stepGenerator(isPlus) {
      var min = this.min,
          max = this.max,
          nonStrictStep = this.nonStrictStep,
          strict = this.strict;
      var options = {
        strict: strict
      };
      var step = defaultTo(this.getProp('step'), 1);
      var value = this.getCurrentInputValue();
      var currentValue = getCurrentValidValue(String(value), options);
      return /*#__PURE__*/_regeneratorRuntime.mark(function _callee(newValue) {
        var nearStep, nextValue, nearMaxStep;
        return _regeneratorRuntime.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                if (!true) {
                  _context.next = 18;
                  break;
                }

                nearStep = nonStrictStep === false ? getNearStepValues(newValue, step, min, max, options) : undefined;

                if (!(nonStrictStep === false && nearStep)) {
                  _context.next = 12;
                  break;
                }

                _context.t0 = nearStep.length;
                _context.next = _context.t0 === 1 ? 6 : _context.t0 === 2 ? 8 : 10;
                break;

              case 6:
                newValue = nearStep[0];
                return _context.abrupt("break", 10);

              case 8:
                newValue = nearStep[isPlus ? 1 : 0];
                return _context.abrupt("break", 10);

              case 10:
                _context.next = 14;
                break;

              case 12:
                nextValue = isPlus ? math.plus(newValue, step, options) : math.minus(newValue, step, options);

                if (!isEmpty(min) && math.lt(nextValue, min)) {
                  newValue = min;
                } else if (!isEmpty(max) && math.gt(nextValue, max)) {
                  nearMaxStep = nonStrictStep === false ? getNearStepValues(max, step, min, max, options) : undefined;

                  if (nonStrictStep === false && nearMaxStep) {
                    newValue = nearMaxStep[0];
                  } else {
                    newValue = max;
                  }
                } else {
                  newValue = nextValue;
                }

              case 14:
                _context.next = 16;
                return newValue;

              case 16:
                _context.next = 0;
                break;

              case 18:
              case "end":
                return _context.stop();
            }
          }
        }, _callee);
      })(currentValue);
    }
  }, {
    key: "getCurrentInputValue",
    value: function getCurrentInputValue() {
      var value;

      if (!isEmpty(this.text)) {
        value = this.text;
      } else if (this.range && !isNil(this.rangeTarget) && this.rangeValue) {
        value = this.rangeValue[this.rangeTarget];
      } else {
        value = this.getValue();
      }

      return value;
    }
  }, {
    key: "step",
    value: function step(isPlus) {
      this.afterStep(this.stepGenerator(isPlus).next().value);
    }
  }, {
    key: "afterStep",
    value: function afterStep(newValue) {
      if (this.multiple) {
        this.setText(String(newValue));
      } else {
        this.prepareSetValue(newValue);
      }
    }
  }, {
    key: "prepareSetValue",
    value: function prepareSetValue(value) {
      if (isNaN(value) || isEmpty(value)) {
        _get(_getPrototypeOf(NumberField.prototype), "prepareSetValue", this).call(this, null);
      } else {
        _get(_getPrototypeOf(NumberField.prototype), "prepareSetValue", this).call(this, parseNumber(value, this.getProp('precision'), this.strict));
      }
    }
  }, {
    key: "getProcessValueOptions",
    value: function getProcessValueOptions() {
      var options = _get(_getPrototypeOf(NumberField.prototype), "getProcessValueOptions", this).call(this);

      options.isNumber = true;
      options.precision = this.getProp('precision');
      options.useZeroFilledDecimal = this.getContextConfig('useZeroFilledDecimal');
      return options;
    }
  }, {
    key: "restrictInput",
    value: function restrictInput(value) {
      if (this.lock) return value;

      if (value) {
        value = value.replace('。', '.');
        var restrict = '0-9';

        if (this.allowDecimal) {
          restrict += '.';
        } else if (value.indexOf('.') !== -1) {
          var boforeValue = this.getCurrentInputValue();
          boforeValue = !isNil(boforeValue) ? String(boforeValue) : '';

          if (boforeValue.indexOf('.') === -1) {
            return boforeValue;
          }

          value = String(this.stepGenerator(false).next().value);
        }

        var isNegative = this.allowNegative && /^-/.test(value);
        value = _get(_getPrototypeOf(NumberField.prototype), "restrictInput", this).call(this, value.replace(new RegExp("[^".concat(restrict, "]+"), 'g'), ''));
        var values = value.split('.');

        if (values.length > 2) {
          value = "".concat(values.shift(), ".").concat(values.join(''));
        }

        if (isNegative) {
          value = "-".concat(value);
        }
      }

      return value;
    }
  }, {
    key: "getFormatOptions",
    value: function getFormatOptions(value) {
      var _this3 = this;

      return getNumberFormatOptions(function (name) {
        return _this3.getProp(name);
      }, function (name) {
        return _this3.getDisplayProp(name);
      }, function () {
        return _this3.getValue();
      }, value, this.lang, this.getContextConfig);
    }
  }, {
    key: "getFormatter",
    value: function getFormatter() {
      return this.getProp('formatter') || getNumberFormatter(this.getContextConfig);
    }
  }, {
    key: "processText",
    value: function processText(value) {
      var fixedValue = math.fix(new BigNumber(String(value)));
      var formatOptions = this.getFormatOptions(fixedValue);
      return this.getFormatter()(value, formatOptions.lang, formatOptions.options);
    }
  }, {
    key: "renderLengthInfo",
    value: function renderLengthInfo() {
      return undefined;
    }
  }, {
    key: "compare",
    value: function compare(oldValue, newValue) {
      return math.eq(oldValue, newValue);
    }
  }, {
    key: "isValidInput",
    value: function isValidInput(input) {
      return !input.endsWith('.');
    }
  }]);

  return NumberField;
}(TextField);
NumberField.displayName = 'NumberField';
NumberField.defaultProps = _objectSpread(_objectSpread({}, TextField.defaultProps), {}, {
  suffixCls: 'input-number',
  longPressPlus: true,
  max: Infinity,
  min: -Infinity
});
NumberField.format = defaultFormatNumber;
/**
 * @deprecated
 */

NumberField.bigNumberFormat = defaultFormatNumber;

__decorate([computed], NumberField.prototype, "lang", null);

__decorate([computed], NumberField.prototype, "allowDecimal", null);

__decorate([computed], NumberField.prototype, "nonStrictStep", null);

__decorate([computed], NumberField.prototype, "allowNegative", null);

__decorate([computed], NumberField.prototype, "min", null);

__decorate([computed], NumberField.prototype, "max", null);

__decorate([computed], NumberField.prototype, "value", null);

__decorate([autobind], NumberField.prototype, "savePlusRef", null);

__decorate([autobind], NumberField.prototype, "saveMinusRef", null);

__decorate([action], NumberField.prototype, "handleEnterDown", null);

__decorate([autobind], NumberField.prototype, "handleKeyDown", null);

__decorate([keepRunning(stepUpKeyboardProps)], NumberField.prototype, "handleKeyDownUp", null);

__decorate([keepRunning(stepDownKeyboardProps)], NumberField.prototype, "handleKeyDownDown", null);

__decorate([keepRunning(stepUpMouseProps)], NumberField.prototype, "handlePlus", null);

__decorate([keepRunning(stepDownMouseProps)], NumberField.prototype, "handleMinus", null);

__decorate([autobind], NumberField.prototype, "handleOncePlus", null);

__decorate([autobind], NumberField.prototype, "handleOnceMinus", null);

__decorate([autobind], NumberField.prototype, "compare", null);

var ObserverNumberField = /*#__PURE__*/function (_NumberField) {
  _inherits(ObserverNumberField, _NumberField);

  var _super2 = _createSuper(ObserverNumberField);

  function ObserverNumberField() {
    _classCallCheck(this, ObserverNumberField);

    return _super2.apply(this, arguments);
  }

  return _createClass(ObserverNumberField);
}(NumberField);

ObserverNumberField.defaultProps = NumberField.defaultProps;
ObserverNumberField.format = defaultFormatNumber;
/**
 * @deprecated
 */

ObserverNumberField.bigNumberFormat = defaultFormatNumber;
ObserverNumberField = __decorate([observer], ObserverNumberField);
export default ObserverNumberField;
//# sourceMappingURL=NumberField.js.map
