/**
 * 类型标签，Object.prototype.toString.call(obj) 的返回值
 */
export enum TypeTag {
  NULL = '[object Null]',
  UNDEFINED = '[object Undefined]',

  STRING = '[object String]',
  NUMBER = '[object Number]',
  BOOLEAN = '[object Boolean]',

  ARRAY = '[object Array]',
  MAP = '[object Set]',
  SET = '[object Map]',

  OBJECT = '[object Object]',
  SYMBOL = '[object Symbol]',
  DATE = '[object Date]',
  REGEXP = '[object RegExp]',
  PROMISE = '[object Promise]',
  FUNCTION = '[object Function]',
}

/**
 * 节流<br/>
 * t 毫秒内只执行一次指定的函数<br/>
 *
 * @param fn 待包装的函数
 * @param t 时间阈值（ms）
 * @return 包装后的函数
 */
export function throttle<T extends any[]>(t: number, fn: (...args: T) => void) {
  let lastExecTime = 0
  return function (this: any, ...args: T) {
    let now = Date.now()
    if (now - lastExecTime >= t) {
      lastExecTime = now
      fn.apply(this, args)
    }
  }
}

/**
 * 防抖<br/>
 * 指定的函数延迟 t 毫秒只执行，重复调用将重新计时<br/>
 *
 * @param fn 待包装的函数
 * @param t 时间阈值（ms）
 * @return 包装后的函数
 */
export function debounce<T extends any[]>(t: number, fn: (...args: T) => void) {
  let deferTimer: number | null = null
  return function (this: any, ...args: T) {
    if (deferTimer != null) {
      clearTimeout(deferTimer)
    }

    deferTimer = window.setTimeout(() => {
      fn.apply(this, args)
    }, t)
  }
}

export function clone<T = any>(t: T) {
  return JSON.parse(JSON.stringify(t)) as T
}

export default {
  throttle,
  debounce,
  TypeTag,
  clone,
}
