import React, { useState, useMemo, useCallback, useContext } from 'react'
import immer from 'immer' // Immer rocks. Go check it out if you haven't

export default function makeStore() {
  // This is basically a factory for a new store instance
  
  // Create a new context for this store instance
  const context = React.createContext()

  // Make a provider that takes an initial state
  const Provider = ({ children, initialState = {} }) => {
    
    // useState will do. Nothing fancy needed
    const [state, preSetState] = useState(initialState)

    // We make our own setState callback that uses immer under the hood
    // (or we could use `useImmer`, but this is fun, too)
    const setState = useCallback(
      updater => preSetState(old => immer(old, draft => updater(draft))),
      preSetState
    )

    // Memoize the context value so it only updates when the state changes
    const contextValue = useMemo(() => [state, setState], [state])

    // Pass the context down
    return <context.Provider value={contextValue}>{children}</context.Provider>
  }

  // A hook to consume the context. No need to import `useContext` everywhere. How wasteful...
  const useStore = () => useContext(context)

  // Export them however you like. I prefer a default.
  return {
    Provider,
    useStore,
  }
}