import math from 'mathjs';
import * as R from 'ramda';

// ----------------------------------------------------------------
// 数学计算工具类 - 处理高精度计算或者数字转化，提供数学算法。
// ----------------------------------------------------------------

// 高精度计算 - 内部统一返回BigDecimal，再统一转成number类型。
const basicHpOperations = (
  (maths): {} => R.fromPairs(R.keys(maths).map((oper): [string, any] =>
    [oper, R.curry(R.compose(parseFloat, (bn): {} => bn.toString(), maths[oper]))]
  ))
)({
  // 高精度加法
  add: (sbj: number, acc: number): {} => {
    return math.add(math.bignumber(sbj), math.bignumber(acc));
  },
  // 高精度减法
  sub: (sbj: number, acc: number): {} => {
    return math.subtract(math.bignumber(sbj), math.bignumber(acc));
  },
  // 高精度乘法
  mul: (sbj: number, acc: number): {} => {
    return math.multiply(math.bignumber(sbj), math.bignumber(acc));
  },
  // 高精度除法
  div: (sbj: number, acc: number): {} => {
    return math.divide(math.bignumber(sbj), math.bignumber(acc));
  }
});

/**
 * Get a random floating point number between `min` and `max`.
 *
 * @param {number} min - min number
 * @param {number} max - max number
 * @return {float} a random floating point number
 */
const getRandom = (min, max): number => {
  return Math.random() * (max - min) + min;
};

/**
 * Get a random integer between `min` and `max`.
 *
 * @param {number} min - min number
 * @param {number} max - max number
 * @return {int} a random integer
 */
const getRandomInt = (min, max): number => {
  return Math.floor(Math.random() * (max - min + 1) + min);
};

/**
 * 检查一个变量是否是数字（不一定是数字类型）
 * 如果是的话，返回解析结果，不是则返回原变量
 * @param candidate - 带判断变量
 * @returns {number | any}
 */
const parseIfNumeric = (candidate): number =>
  (// Number(parseFloat(candidate)) === +candidate
    (typeof candidate === 'number') || (+candidate + '' === candidate)
  ) ? +candidate : candidate;

export default {
  ...basicHpOperations, // 将内部计算解构成4种计算
  parseIfNumeric,
  getRandom,
  getRandomInt
};
