import { useState, useCallback, useEffect, useRef } from "react";

export function useToggle(init = false) {
  const [bool, setBool] = useState(init);
  const toggle = useCallback(() => {
    setBool((old) => !old);
  }, []);
  return [bool, toggle];
}

export function useForceUpdate() {
  const [_, setVer] = useState(0);
  return useCallback(() => {
    setVer((v) => v + 1);
  }, []);
}

export function useMap(canAdd, canRemove = () => true) {
  const mapRef = useRef(new Map());
  const forceUpdate = useForceUpdate();
  const add = useCallback((key, item) => {
    if (!canAdd(mapRef.current)) {
      return;
    }
    mapRef.current.set(key, item);
    forceUpdate();
  }, []);
  const remove = useCallback((key) => {
    mapRef.current.delete(key);
    forceUpdate();
  }, []);
  return { map: mapRef.current, add, remove };
}

export function useLoaded(promiseFac, dependsLst) {
  const [isLoaded, setLoaded] = useState(false);
  const dataRef = useRef(null);
  useEffect(() => {
    const f = async () => {
      dataRef.current = await promiseFac(...dependsLst);
      setLoaded(true);
    };
    f();
    return () => {
      setLoaded(false);
    };
  }, dependsLst);
  return { isLoaded, data: dataRef.current };
}

export function useSet(canAdd = () => true) {
  const setRef = useRef(new Set());
  const forceUpdate = useForceUpdate();
  const add = useCallback((key) => {
    if(canAdd(setRef.current)){
      setRef.current.add(key);
      forceUpdate();
    }
  }, []);
  const remove = useCallback((key) => {
    setRef.current.delete(key);
    forceUpdate();
  }, []);
  return { set: setRef.current, add, remove };
}
