class Debounce {

  constructor() {
    this.timers = new Map();
    this.counters = new Map();
    this.v3 = new Map();
  }

  // 增加倒计时功能和连续点击触发功能
  // key: 唯一键
  // callback: 目标事件
  // interrupt: 中断事件
  // wait: 倒计时时间

  // 执行防抖操作的方法
  do(key, callback, wait = 300) {
    if (this.timers.has(key)) {
      clearTimeout(this.timers.get(key));
    }

    const timer = setTimeout(() => {
      callback();
      this.timers.delete(key);
    }, wait);

    this.timers.set(key, timer);
  }

  /**
   *
   * @param key
   * @param options
   * @param {number} [options.duration=10000] - 总倒计时时长（毫秒）。
   * @param {function} [options.callback=null] - 每秒回调事件。
   * @param {function} [options.endCallback=null] - 倒计时结束事件。
   * @param {function} [options.restart=false] - 再次点击是否重新计时。
   */
  countDown(key, options) {
    let op = {
      duration: options.duration || 10000, // 总倒计时时长（毫秒）
      callback: options.callback || null, // 每秒回调事件
      endCallback: options.endCallback || null, // 倒计时结束事件
      restart: options.restart || false, // 是否点击重新计时
    };
    if (op.restart || !this.counters.has(key)) {
      const tick = () => {
        const timer = this.counters.get(key);
        if (timer.remainingTime <= 0) {
          clearTimeout(timer.timeoutId);
          if (op.endCallback) op.endCallback();
          this.counters.delete(key);
        } else {
          timer.remainingTime -= 1000;
          if (op.callback) op.callback(Math.ceil(timer.remainingTime / 1000));
          timer.timeoutId = setTimeout(tick, 1000);
          this.counters.set(key, timer);
        }
      };

      this.counters.set(key, {
        remainingTime: op.duration,
        timeoutId: setTimeout(tick, 1000),
      });

      // 立即执行一次回调
      if (op.callback) op.callback(Math.ceil(op.duration / 1000));
    }
  }

  /**
   * 开始一个倒计时，支持每秒回调、成功和失败事件。
   * @param {string} key - 倒计时的唯一标识。
   * @param {{fail: fail, success: success, limit: number, run: run, time: number, repetition_time: number}} options - 倒计时的配置选项。
   * @param {number} [options.time=10000] - 总倒计时时长（毫秒）。
   * @param {number} [options.limit=5] - 连续操作的次数目标。
   * @param {function(second, count, boolean):void} [options.run] - 每秒执行的回调函数(剩余秒数,当前被点击次数,是否被点击）。
   * @param {function():void} [options.success] - 达到目标次数后的成功回调。
   * @param {function():void} [options.fail] - 倒计时结束的失败回调。
   * @param {boolean} [options.restart_time=false] - 是否点击重新计时。
   * @param {boolean} [options.repetition_time=0] - 重复点击限制时长(毫秒)。
   */
  secondCountDown(key, options = {}) {
    let op = {
      time: options.time || 10000, // 总倒计时长(毫秒)
      limit: options.limit || 5, // 连续操作的次数目标
      run: options.run || null, // 每秒都返回更改页面倒计时文字
      success: options.success || null, // 达到目标次数后的成功回调
      fail: options.fail || null, // 倒计时结束的失败回调
      restart_time: options.restart_time || false, // 是否点击重新计时
      repetition_time: options.repetition_time || -1, // 重复点击限制时长(毫秒) -1 为不重置
    };
    let counter = this.counters.get(key) || {
      type: 2,
      count: 0,
      timer: null,
      startTime: Date.now(),
      remainingTime: op.time,
      inform: true,
      repetition: null,
    };

    if (counter.timer) {
      clearTimeout(counter.timer);
      counter.timer = null;
    }

    // 仅当op.restart_time为true时重置时间，点击次数不重置
    if (op.restart_time) {
      counter.startTime = Date.now();
      counter.remainingTime = op.time;
      counter.inform = true;
    }

    const tick = () => {
      let elapsed = Date.now() - counter.startTime;
      let remaining = op.time - elapsed;
      if (remaining <= 0) {
        // 时间到，执行失败事件
        op.fail && op.fail();
        this.counters.delete(key);
      } else {
        // 更新剩余时间并执行运行回调
        counter.remainingTime = remaining;
        op.run && op.run(Math.ceil(remaining / 1000), counter.count, counter.inform);
        counter.inform = false;
        counter.timer = setTimeout(tick, 1000);
        this.counters.set(key, counter);
      }
    };

    counter.count += 1;
    counter.inform = true // 每次点击都重新通知
    if (counter.count >= op.limit) {
      // 达到点击次数，执行成功事件
      clearTimeout(counter.timer);
      op.success && op.success();
      if (op.repetition_time < 0) {
      } else if (op.repetition_time === 0) {
        this.counters.delete(key);
      } else if (op.repetition_time > 0 && !counter.repetition) {
        let that = this
        counter.repetition = setTimeout(() => {
          that.counters.delete(key);
        }, op.repetition_time)
        this.counters.set(key, counter);
      }
    } else {
      // 更新计数器状态
      this.counters.set(key, counter);
      // 继续倒计时
      if (!counter.timer) {
        tick();
      }
    }
  }


  clearDebounce(key) {
    let counter = this.counters.get(key)
    if (!counter) return;
    if (counter.timer) clearTimeout(counter.timer)
    switch (counter.type) {
      case 2:
        if (counter.repetition) clearTimeout(counter.repetition)
        break;
    }
    this.counters.delete(key)
  }


}

export default Debounce
