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

import { ShowToastThroughManagerOptions, WithToastIdProps } from '../types';

/** Values of {@link ToastManagerContext} */
interface ToastManagerContextValue {
  /** Show given component as Toast */
  showToast: (
    component: (props: WithToastIdProps) => JSX.Element,
    options?: ShowToastThroughManagerOptions,
  ) => void;
  /** Hide Toast with given ID */
  hideToast: (id: string) => void;
}

const ToastManagerContext = createContext<Readonly<ToastManagerContextValue> | undefined>(undefined);

/** Context that should be used by {@link ToastManager} */
export function ToastManagerContextProvider({
  showToast,
  hideToast,
  children,
}: PropsWithChildren<ToastManagerContextValue>) {
  const value: ToastManagerContextValue = useMemo(() => ({ showToast, hideToast }), [showToast, hideToast]);

  return <ToastManagerContext.Provider value={value}>{children}</ToastManagerContext.Provider>;
}

/** Returns value of context for {@link ToastManager} */
export function useToastManagerContext() {
  const value = useContext(ToastManagerContext);
  if (!value) {
    throw new Error('useToastManagerContext should be used only inside ToastManagerContextProvider');
  }

  return value;
}
