import type { AxiosRequestConfig, Canceler } from 'axios';

import axios from 'axios';

import { isFunction } from '/@/utils/is';



// Used to store the identification and cancellation function of each request

let pendingMap = new Map<string, Canceler>();



export const getPendingUrl = (config: AxiosRequestConfig) => [config.method, config.url].join('&');



export class AxiosCanceler {

  /**

   * Add request

   * @param {Object} config

   */

  addPending(config: AxiosRequestConfig) {

    this.removePending(config);

    const url = getPendingUrl(config);

    config.cancelToken =

      config.cancelToken ||

      new axios.CancelToken((cancel) => {

        if (!pendingMap.has(url)) {

          // If there is no current request in pending, add it

          pendingMap.set(url, cancel);

        }

      });

  }



  /**

   * @description: Clear all pending

   */

  removeAllPending() {

    pendingMap.forEach((cancel) => {

      cancel && isFunction(cancel) && cancel();

    });

    pendingMap.clear();

  }



  /**

   * Removal request

   * @param {Object} config

   */

  removePending(config: AxiosRequestConfig) {

    const url = getPendingUrl(config);



    if (pendingMap.has(url)) {

      // If there is a current request identifier in pending,

      // the current request needs to be cancelled and removed

      const cancel = pendingMap.get(url);

      cancel && cancel(url);

      pendingMap.delete(url);

    }

  }



  /**

   * @description: reset

   */

  reset(): void {

    pendingMap = new Map<string, Canceler>();

  }

}