import React, {
  createContext,
  MutableRefObject,
  useState,
  useMemo,
  useContext,
  useCallback
} from 'react'
import Toast, { Props } from './index'
import { ToastType, VisibleToastsType, ToastContextType, ToastList } from "./types"

// 创建一个createContext
const ToastContext = createContext<ToastContextType>({
  toastList: {},
  visibleToasts: {},
  setToast: () => { },
  hideToast: () => { },
  hideAll: () => { },
  loading: () => { }
});
// 组件调用Context
const CustomToast = () => {
  const { toastList, visibleToasts, hideToast } = useContext(ToastContext)
  const toastListIds = () => {
    return Object.keys(visibleToasts)
  }
  return (<>
    {
      toastListIds().map((id) => {
        return (<Toast key={id} onChange={() => hideToast(id)} show={visibleToasts[id]} {...toastList[id]}></Toast>)
      })
    }

  </>)
}
// 组件调用Context
export const ToastProvider = ({ children }: { children: any }) => {
  const [toastList, setToastList] = useState<ToastList>({})
  const [visibleToasts, setVisibleToasts] = useState<VisibleToastsType>({});
  const toastIndex = React.useRef(7000);
  const hideToast = useCallback(
    (id: any) => {
      setVisibleToasts((prev) => {
        return { ...prev, [id]: false }
      })
    }, [setVisibleToasts])
  const hideAll = useCallback(() => {
    setVisibleToasts({})
  }, [setVisibleToasts])
  const setToast = useCallback(
    (props: ToastType): number => {
      const {
        id = toastIndex.current++,
        ...rest
      } = props
      setToastList((prev) => {
        return {
          ...prev, [id]: {
            id,
            ...rest
          }
        }
      })
      setVisibleToasts((prev) => {
        return { ...prev, [id]: true }
      })
      return id
    },
    [toastList, visibleToasts, hideToast]
  )
  const loading = useCallback(
    (props: ToastType): number => {
      const {
        id = toastIndex.current++,
        ...rest
      } = props
      setToastList((prev) => {
        return {
          ...prev, [id]: {
            id,
            icon: "loading1",
            duration: 0,
            loading: true,
            ...rest
          }
        }
      })
      setVisibleToasts((prev) => {
        return { ...prev, [id]: true }
      })
      return id
    },
    [toastList, visibleToasts, hideToast]
  )
  const contextValue = useMemo(() => {
    return {
      toastList,
      visibleToasts,
      setToast,
      hideToast,
      hideAll,
      loading
    }
  }, [toastList, visibleToasts, setToast, hideToast, hideAll, loading])
  return (
    <ToastContext.Provider value={contextValue}>
      {children}
      <CustomToast></CustomToast>
    </ToastContext.Provider>
  )
}


export const useToast = () => {
  const { setToast, hideToast, hideAll, loading } = React.useContext(
    ToastContext
  );
  const toast = useMemo(
    () => ({
      show: setToast,
      close: hideToast,
      closeAll: hideAll,
      loading: loading
    }),
    [setToast, hideToast, hideAll, loading]
  );

  return toast;
}

//!这部分和ref相关的
export type IToastService = ReturnType<typeof useToast>;

export const ToastRef = React.createRef<IToastService>() as MutableRefObject<IToastService>;

export const _Toast: IToastService = {
  show: (props: Props) => ToastRef.current?.show(props),
  close: (id: any) => ToastRef.current?.close(id),
  closeAll: () => ToastRef.current?.closeAll(),
  loading: (props: Props) => ToastRef.current?.show(props),
  // isActive: (id: any) => ToastRef.current?.isActive(id),
};