import { useEffect, useMemo, useReducer } from "react"
import { createContext, useContextSelector } from "use-context-selector"
import { debounce } from "lodash"
import json from "superjson"
import { type RootState, rootReducer } from "./state"

export * from "./selectors"

export const LOCAL_STORAGE_KEY = "options:state"
const preloadedState: RootState = (() => {
  try {
    const state = localStorage.getItem(LOCAL_STORAGE_KEY)
    if (state) {
      return json.parse(state)
    }
  } catch {}

  return {
    tabs: [],
    dirtyFileIds: new Set(),
  } as RootState
})()

const saveState = debounce((state: RootState) => {
  try {
    localStorage.setItem(LOCAL_STORAGE_KEY, json.stringify(state))
  } catch {}
}, 200)

export let currentState: RootState = preloadedState

function useRootContextValue() {
  const [state, dispatch] = useReducer(rootReducer, preloadedState)

  useEffect(() => {
    currentState = state
    saveState(state)
  }, [state])

  return useMemo(() => ({ state, dispatch }), [state])
}

const Context = createContext<ReturnType<typeof useRootContextValue>>(null!)
const { Provider } = Context

export function RootContextProvider({ children }: { children?: React.ReactNode }) {
  return <Provider value={useRootContextValue()}>{children}</Provider>
}

export const useDispatch = () => useContextSelector(Context, ({ dispatch }) => dispatch)

export const useSelector = <T,>(selector: (state: RootState) => T): T =>
  useContextSelector(Context, ({ state }) => selector(state))
