import { DoubleQueue } from '@/utils/double-queue';
import { defineStore } from 'pinia';
import { markRaw, reactive, readonly, ref } from 'vue';

export type BackgroundURL = string | undefined;
export type BackgroundOptions = {
  resolveTiming: 'transitionStart' | 'transitionEnd';
};
export type BackgroundTask = {
  url: BackgroundURL;
  options: BackgroundOptions;
  addFuture: PromiseWithResolvers<void>;
};

export class CancelledError extends Error {}
export const useBackgroundStore = defineStore('background', () => {
  const taskQueue = new DoubleQueue<BackgroundTask>();
  const getFuturesMap = new Map<number, PromiseWithResolvers<BackgroundTask>>();
  const maxCompId = ref(0);

  function getURL(id: number) {
    const future = Promise.withResolvers<BackgroundTask>();
    if (taskQueue.size) {
      future.resolve(taskQueue.shift()!);
    } else {
      getFuturesMap.set(id, future);
    }
    return future.promise;
  }

  function addURL(
    url: BackgroundURL,
    options: BackgroundOptions = { resolveTiming: 'transitionEnd' },
  ) {
    const addFuture = Promise.withResolvers<void>();
    // addFuture.promise.then(() => console.log('resolve', getFuturesMap));
    // addFuture.promise.catch(() => console.log('reject', getFuturesMap));
    const task: BackgroundTask = {
      url,
      options,
      addFuture: addFuture,
    };
    if (getFuturesMap.size) {
      const [[id, getFuture]] = getFuturesMap;
      getFuturesMap.delete(id);
      getFuture.resolve(task);
    } else {
      taskQueue.push(task);
    }
    return addFuture.promise;
  }

  function newCompId() {
    return maxCompId.value++;
  }

  function unregisterComp(id: number) {
    getFuturesMap.get(id)?.reject(new CancelledError());
    getFuturesMap.delete(id);
  }

  function $reset() {
    for (const task of taskQueue) {
      task.addFuture.reject(new CancelledError());
    }
    console.log(taskQueue);
    for (const id of [...getFuturesMap.keys()]) {
      unregisterComp(id);
    }
  }

  return {
    getURL,
    addURL,
    newCompId,
    unregisterComp,
    $reset,
  };
});
