'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var numberUtil = require('./numberUtil.cjs');
var supportUtil = require('./supportUtil.cjs');

var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  return value;
};
function isEmpty(value) {
  return !value && value !== 0 && !Number.isNaN(value) || !String(value).trim();
}
class NumberDecimal {
  constructor(value) {
    __publicField(this, "origin", "");
    __publicField(this, "number");
    __publicField(this, "empty");
    if (isEmpty(value)) {
      this.empty = true;
      return;
    }
    this.origin = String(value);
    this.number = Number(value);
  }
  negate() {
    return new NumberDecimal(-this.toNumber());
  }
  add(value) {
    if (this.isInvalidate())
      return new NumberDecimal(value);
    const target = Number(value);
    if (Number.isNaN(target))
      return this;
    const number = this.number + target;
    if (number > Number.MAX_SAFE_INTEGER)
      return new NumberDecimal(Number.MAX_SAFE_INTEGER);
    if (number < Number.MIN_SAFE_INTEGER)
      return new NumberDecimal(Number.MIN_SAFE_INTEGER);
    const maxPrecision = Math.max(numberUtil.getNumberPrecision(this.number), numberUtil.getNumberPrecision(target));
    return new NumberDecimal(number.toFixed(maxPrecision));
  }
  isEmpty() {
    return this.empty;
  }
  isNaN() {
    return Number.isNaN(this.number);
  }
  isInvalidate() {
    return this.isEmpty() || this.isNaN();
  }
  equals(target) {
    return this.toNumber() === (target == null ? void 0 : target.toNumber());
  }
  lessEquals(target) {
    return this.add(target.negate().toString()).toNumber() <= 0;
  }
  toNumber() {
    return this.number;
  }
  toString(safe = true) {
    if (!safe)
      return this.origin;
    if (this.isInvalidate())
      return "";
    return numberUtil.num2str(this.number);
  }
}
class BigIntDecimal {
  constructor(value) {
    __publicField(this, "origin", "");
    __publicField(this, "negative");
    __publicField(this, "integer");
    __publicField(this, "decimal");
    /** BigInt will convert `0009` to `9`. We need record the len of decimal */
    __publicField(this, "decimalLen");
    __publicField(this, "empty");
    __publicField(this, "nan");
    if (isEmpty(value)) {
      this.empty = true;
      return;
    }
    this.origin = String(value);
    if (value === "-" || Number.isNaN(value)) {
      this.nan = true;
      return;
    }
    let mergedValue = value;
    if (numberUtil.isE(mergedValue))
      mergedValue = Number(mergedValue);
    mergedValue = typeof mergedValue === "string" ? mergedValue : numberUtil.num2str(mergedValue);
    if (numberUtil.validateNumber(mergedValue)) {
      const trimRet = numberUtil.trimNumber(mergedValue);
      this.negative = trimRet.negative;
      const numbers = trimRet.trimStr.split(".");
      this.integer = BigInt(numbers[0]);
      const decimalStr = numbers[1] || "0";
      this.decimal = BigInt(decimalStr);
      this.decimalLen = decimalStr.length;
    } else {
      this.nan = true;
    }
  }
  getMark() {
    return this.negative ? "-" : "";
  }
  getIntegerStr() {
    return this.integer.toString();
  }
  getDecimalStr() {
    return this.decimal.toString().padStart(this.decimalLen, "0");
  }
  /**
   * Align BigIntDecimal with same decimal length. e.g. 12.3 + 5 = 1230000
   * This is used for add function only.
   */
  alignDecimal(decimalLength) {
    const str = `${this.getMark()}${this.getIntegerStr()}${this.getDecimalStr().padEnd(
      decimalLength,
      "0"
    )}`;
    return BigInt(str);
  }
  negate() {
    const clone = new BigIntDecimal(this.toString());
    clone.negative = !clone.negative;
    return clone;
  }
  add(value) {
    if (this.isInvalidate())
      return new BigIntDecimal(value);
    const offset = new BigIntDecimal(value);
    if (offset.isInvalidate())
      return this;
    const maxDecimalLength = Math.max(this.getDecimalStr().length, offset.getDecimalStr().length);
    const myAlignedDecimal = this.alignDecimal(maxDecimalLength);
    const offsetAlignedDecimal = offset.alignDecimal(maxDecimalLength);
    const valueStr = (myAlignedDecimal + offsetAlignedDecimal).toString();
    const { negativeStr, trimStr } = numberUtil.trimNumber(valueStr);
    const hydrateValueStr = `${negativeStr}${trimStr.padStart(maxDecimalLength + 1, "0")}`;
    return new BigIntDecimal(
      `${hydrateValueStr.slice(0, -maxDecimalLength)}.${hydrateValueStr.slice(-maxDecimalLength)}`
    );
  }
  isEmpty() {
    return this.empty;
  }
  isNaN() {
    return this.nan;
  }
  isInvalidate() {
    return this.isEmpty() || this.isNaN();
  }
  equals(target) {
    return this.toString() === (target == null ? void 0 : target.toString());
  }
  lessEquals(target) {
    return this.add(target.negate().toString()).toNumber() <= 0;
  }
  toNumber() {
    if (this.isNaN())
      return Number.NaN;
    return Number(this.toString());
  }
  toString(safe = true) {
    if (!safe)
      return this.origin;
    if (this.isInvalidate())
      return "";
    return numberUtil.trimNumber(`${this.getMark()}${this.getIntegerStr()}.${this.getDecimalStr()}`).fullStr;
  }
}
function getMiniDecimal(value) {
  if (supportUtil.supportBigInt())
    return new BigIntDecimal(value);
  return new NumberDecimal(value);
}
function toFixed(numStr, separatorStr, precision, cutOnly = false) {
  if (numStr === "")
    return "";
  const { negativeStr, integerStr, decimalStr } = numberUtil.trimNumber(numStr);
  const precisionDecimalStr = `${separatorStr}${decimalStr}`;
  const numberWithoutDecimal = `${negativeStr}${integerStr}`;
  if (precision >= 0) {
    const advancedNum = Number(decimalStr[precision]);
    if (advancedNum >= 5 && !cutOnly) {
      const advancedDecimal = getMiniDecimal(numStr).add(
        `${negativeStr}0.${"0".repeat(precision)}${10 - advancedNum}`
      );
      return toFixed(advancedDecimal.toString(), separatorStr, precision, cutOnly);
    }
    if (precision === 0)
      return numberWithoutDecimal;
    return `${numberWithoutDecimal}${separatorStr}${decimalStr.padEnd(precision, "0").slice(0, precision)}`;
  }
  if (precisionDecimalStr === ".0")
    return numberWithoutDecimal;
  return `${numberWithoutDecimal}${precisionDecimalStr}`;
}

exports.BigIntDecimal = BigIntDecimal;
exports.NumberDecimal = NumberDecimal;
exports.default = getMiniDecimal;
exports.toFixed = toFixed;
//# sourceMappingURL=MiniDecimal.cjs.map
