import { use, useEffect, useState } from "react";

export function createUseService<T>(loader: () => Promise<T>) {
  let state: number = 0;
  let listeners = new Set<(state: number) => void>();
  let promise: Promise<T> | undefined;

  function listenToPromise(promise: Promise<T>) {
    state = 1;

    promise.then(
      () => {
        state = 2;
        listeners.forEach((cb) => cb(state));
      },
      () => {
        state = 3;
        listeners.forEach((cb) => cb(state));
      }
    );
  }

  function useService() {
    if (promise === undefined) {
      listenToPromise((promise = loader()));
    }

    return use(promise);
  }

  function useIsServiceLoaded() {
    const [localState, setLocalState] = useState(state);

    useEffect(() => {
      listeners.add(setLocalState);
      return () => listeners.delete(setLocalState);
    }, []);

    return localState === 2 || localState === 3;
  }

  function useIsServiceFailed() {
    const [localState, setLocalState] = useState(state);

    useEffect(() => {
      listeners.add(setLocalState);
      return () => listeners.delete(setLocalState);
    }, []);

    return localState === 3;
  }

  return {
    useService,
    useIsServiceLoaded,
    useIsServiceFailed,
  };
}
