import { useCallback, useEffect, useMemo, useState } from 'react';

const syncValues = {} as Record<string, any>;
const syncValuesListeners = {} as Record<string, ((value: any) => void)[]>;

export default function useSynchronizedState<T>(
  key: string | null,
  initialValue: T
) {
  const [value, setValue] = useState<T>(
    key ? (syncValues[key] ?? initialValue) : initialValue
  );

  useEffect(() => {
    if (key) {
      if (!syncValuesListeners[key]) {
        syncValuesListeners[key] = [];
      }
      syncValuesListeners[key].push(setValue);
      return () => {
        syncValuesListeners[key] = syncValuesListeners[key].filter(
          (listener) => listener !== setValue
        );
      };
    }
  }, [key, setValue]);

  const setAndPropagateValue = useCallback(
    (value: T) => {
      if (key) {
        syncValues[key] = value;
        if (syncValuesListeners[key]) {
          for (const listener of syncValuesListeners[key]) {
            listener(value);
          }
        }
      }

      setValue(value);
    },
    [key]
  );

  return useMemo(
    () => [value, setAndPropagateValue] as const,
    [value, setAndPropagateValue]
  );
}
