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

export const useHashQuery = <T>(
  key: string,
  defaultValue: T
): [T, (value: T) => void] => {
  const parseHashQuery = (): URLSearchParams => {
    const hash = window.location.hash.startsWith("#")
      ? window.location.hash.slice(1)
      : "";
    const queryIndex = hash.indexOf("?");
    return new URLSearchParams(
      queryIndex !== -1 ? hash.slice(queryIndex + 1) : ""
    );
  };

  const setHashQuery = (params: URLSearchParams) => {
    const hash = window.location.hash.split("?")[0];
    window.location.hash = `${hash}?${params.toString()}`;
  };

  const getValue = useCallback(() => {
    const params = parseHashQuery();
    const value = params.get(key);
    return value ? (JSON.parse(value) as T) : defaultValue;
  }, [defaultValue, key]);

  const [state, setState] = useState<T>(getValue);

  const setQuery = useCallback(
    (value: T) => {
      const params = parseHashQuery();
      params.set(key, JSON.stringify(value));
      setHashQuery(params);
      setState(value);
    },
    [key]
  );

  useEffect(() => {
    const onHashChange = () => {
      setState(getValue());
    };

    window.addEventListener("hashchange", onHashChange);
    return () => {
      window.removeEventListener("hashchange", onHashChange);
    };
  }, [key, getValue]);

  return [state, setQuery];
};
