"use client"

import React from "react"
import { createContext } from "use-context-selector"
import { useWindowSize } from "../../hooks"

type SizeProviderProps = {
  children: React.ReactNode
}

export type Size = {
  height: number
  width: number
}

type CreateSizeProviderProps<TSize extends Partial<Size>> = {
  initialWindowSize?: TSize
}

export const createSizeProvider = <TSize extends Partial<Size>>({
  initialWindowSize,
}: CreateSizeProviderProps<TSize>) => {
  type SizeWithInitialSize = TSize & Partial<Size>

  const defaultSize =
    initialWindowSize ||
    ({
      height: 0,
      width: 0,
    } as SizeWithInitialSize)

  const SizeContext = createContext<SizeWithInitialSize>(defaultSize)

  /*
   * Creates a ContextProvider for a centralized source of screen width/height.
   *
   * This ensures there is only a single event listener attached for the resize event and not one for each component.
   *
   * IMPORTANT: Its important to write a specialised context selector to only get the value you care about (e.g isLessThanMd) instead
   * of subscribing to the width/height directly. This ensures that the component will re-render only if the actual value of the breakpoint changes,
   * and not on every resize event.
   */ const SizeProvider = ({ children }: SizeProviderProps) => {
    const windowSize = useWindowSize<SizeWithInitialSize>(
      initialWindowSize as SizeWithInitialSize,
    )
    return (
      <SizeContext.Provider value={windowSize}>{children}</SizeContext.Provider>
    )
  }

  return { SizeProvider, SizeContext }
}
