'use strict';

function debounce(func, delay = 500, immediate, resultCallback) {
  let timer = null;
  let isInvoke = false;
  const _debounce = function(...args) {
    return new Promise((resolve, reject) => {
      if (timer) clearTimeout(timer);
      if (immediate && !isInvoke) {
        try {
          const result = func.apply(this, args);
          if (resultCallback) resultCallback(result);
          resolve(result);
        } catch (e) {
          reject(e);
        }
        isInvoke = true;
      } else {
        timer = setTimeout(() => {
          try {
            const result = func.apply(this, args);
            if (resultCallback) resultCallback(result);
            resolve(result);
          } catch (e) {
            reject(e);
          }
          isInvoke = false;
          timer = null;
        }, delay);
      }
    });
  };
  _debounce.cancel = function() {
    if (timer) clearTimeout(timer);
    isInvoke = false;
    timer = null;
  };
  return _debounce;
}
function throttle(func, interval, options = { leading: false, trailing: true }) {
  let timer = null;
  let lastTime = 0;
  const { leading, trailing } = options;
  const _throttle = function(...args) {
    const nowTime = Date.now();
    if (!lastTime && !leading) lastTime = nowTime;
    const remainTime = interval - (nowTime - lastTime);
    if (remainTime <= 0) {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
      lastTime = nowTime;
      func.apply(this, args);
    }
    if (trailing && !timer) {
      timer = setTimeout(() => {
        lastTime = !leading ? 0 : Date.now();
        timer = null;
        func.apply(this, args);
      }, remainTime);
    }
  };
  _throttle.cancel = function() {
    if (timer) clearTimeout(timer);
    timer = null;
    lastTime = 0;
  };
  return _throttle;
}
function toLine(name) {
  return name.replace(/([A-Z])/g, "_$1").toLowerCase();
}
function formatNumber(value, precision = 2, separator = ",", decimal = ".", prefix = "", suffix = "") {
  if (Number(value) === 0) {
    return Number(value).toFixed(precision);
  }
  if (!value) {
    return "";
  }
  value = Number(value).toFixed(precision);
  value += "";
  const nums = value.split(".");
  let integer = nums[0];
  const decimals = nums.length > 1 ? decimal + nums[1] : "";
  const reg = /(\d+)(\d{3})/;
  function isNumber(value2) {
    return Object.prototype.toString.call(value2) === "[object Number]";
  }
  if (separator && !isNumber(separator)) {
    while (reg.test(integer)) {
      integer = integer.replace(reg, "$1" + separator + "$2");
    }
  }
  return prefix + integer + decimals + suffix;
}

exports.debounce = debounce;
exports.formatNumber = formatNumber;
exports.throttle = throttle;
exports.toLine = toLine;
