import { createContext, PropsWithChildren, useContext, useState } from 'react';

interface IContext {
  getValue: <T>(key: string) => T | undefined;
  setValue: <T>(key: string, value: T) => void;
}

const AppStateContext = createContext<IContext | undefined>(undefined);

const AppStateContextProvider = ({ children }: PropsWithChildren<{}>) => {
  const [appState, setAppState] = useState<Record<string, any>>({});

  const getValue = <T,>(key: string) => appState[key] as T;

  const setValue = <T,>(key: string, value: T) =>
    setAppState((prevAppState) => ({ ...prevAppState, [key]: value }));

  return (
    <AppStateContext.Provider value={{ getValue, setValue }}>{children}</AppStateContext.Provider>
  );
};

const useAppState = <T,>(key: string): [T | undefined, (value: T) => void] => {
  const context = useContext(AppStateContext);
  if (!context) {
    // This is an error message for the developer
    throw new Error('useAppState must be used inside a AppStateContextProvider.');
  }

  const { getValue, setValue } = context;
  return [getValue<T>(key), (value: T) => setValue(key, value)];
};

export { AppStateContextProvider, useAppState };
