/**
 * 函数相关类
 */
export class FuncManager {
  constructor() {
    // 防抖定时器
    this.timeout = null;
    // 节流定时器
    this.timer = null;
    this.flag = null;
  }

  /**
   * @description 进行延时，以达到可以简写代码的目的 比如: await sleep(20)将会阻塞20ms
   * @param {number} value 堵塞时间 单位ms 毫秒
   * @returns {Promise} 返回promise
   */
  sleep = (value = 30) => {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve()
      }, value)
    })
  }

  /**
   * 是否是函数
   */
  isFunc = (value) => {
    return typeof value === 'function'
  }

  /**
   * 防抖原理：一定时间内，只有最后一次操作，再过wait毫秒后才执行函数
   *
   * @param {Function} func 要执行的回调函数
   * @param {Number} wait 延时的时间
   * @param {Boolean} immediate 是否立即执行
   * @return null
   */
  debounce = (func, wait = 500, immediate = false) => {
    // 清除定时器
    if (this.timeout !== null) clearTimeout(this.timeout)
    // 立即执行，此类情况一般用不到
    if (immediate) {
      const callNow = !this.timeout
      this.timeout = setTimeout(() => {
        this.timeout = null
      }, wait)
      if (callNow) typeof func === 'function' && func()
    } else {
      // 设置定时器，当最后一次操作后，timeout不会再被清除，所以在延时wait毫秒后执行func回调方法
      this.timeout = setTimeout(() => {
        typeof func === 'function' && func()
      }, wait)
    }
  }

  /**
   * 节流原理：在一定时间内，只能触发一次
   *
   * @param {Function} func 要执行的回调函数
   * @param {Number} wait 延时的时间
   * @param {Boolean} immediate 是否立即执行
   * @return null
   */
  throttle = (func, wait = 500, immediate = true) => {
    if (immediate) {
      if (!this.flag) {
        this.flag = true
        // 如果是立即执行，则在wait毫秒内开始时执行
        typeof func === 'function' && func()
        this.timer = setTimeout(() => {
          this.flag = false
        }, wait)
      }
    } else if (!this.flag) {
      this.flag = true
      // 如果是非立即执行，则在wait毫秒内的结束处执行
      this.timer = setTimeout(() => {
        this.flag = false
        typeof func === 'function' && func()
      }, wait)
    }
  }

  /**
   * 显示消息提示框
   * @param {String} title 提示的内容，长度与 icon 取值有关。
   * @param {Function} func 执行完后的执行函数
   * @param {Number} duration 提示的延迟时间，单位毫秒，默认：2000
   */
  toast = (title, func = null, duration = 2000) => {
    uni.showToast({
      title: String(title),
      icon: 'none',
      duration
    })
    if (typeof func === "function") {
      setTimeout(() => {
        func();
      }, duration)
    }
  }
}