import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { AccountLocalStorageContext } from './useAccountLocalStorage';

function useStorageBackedState<T>(defaultValue: T, storageKey: string | false, storeDefaultIfNotStored = false) {
  const { localStorage } = useContext(AccountLocalStorageContext);
  const initialValueString = useMemo(() => storageKey && localStorage.getItem(storageKey), [localStorage, storageKey]);
  const initialValue =
    initialValueString && initialValueString !== 'undefined' ? JSON.parse(initialValueString) : defaultValue;
  const [value, setValue] = useState<T>(initialValue);

  const onSetValue = useCallback(
    (newValue: T | ((previous: T) => T)) => {
      let valueToStore = newValue;
      if (newValue instanceof Function) {
        setValue((previous) => {
          const outputValue = newValue(previous);
          valueToStore = outputValue;
          storageKey && localStorage.setItem(storageKey, JSON.stringify(valueToStore));
          return outputValue;
        });
      } else {
        setValue(newValue);
        localStorage && storageKey && localStorage.setItem(storageKey, JSON.stringify(valueToStore));
      }
    },
    [localStorage, storageKey]
  );

  useEffect(() => {
    if (storeDefaultIfNotStored && storageKey && !localStorage.keys().includes(storageKey)) {
      onSetValue(defaultValue);
    }
  }, [localStorage, defaultValue, onSetValue, storageKey, storeDefaultIfNotStored]);

  return useMemo(() => [value, onSetValue] as [typeof value, typeof onSetValue], [onSetValue, value]);
}

export default useStorageBackedState;
