import React, { useContext, useState } from "react";

import Button from "@mui/material/Button";
import Dialog, { DialogProps } from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";

type BananasDialogProps = Omit<DialogProps, "open">;

const DialogContext = React.createContext<{
  title: string;
  children: React.ReactNode;
  cb: (ok: boolean) => void;
  open: boolean;
  makeOpen: (
    title: string,
    children: React.ReactNode,
    options?: {
      ok?: string | false;
      cancel?: string | false;

      dialogProps?: BananasDialogProps;
    },
  ) => Promise<boolean>;

  dialogProps: BananasDialogProps;
  ok: string | false;
  cancel: string | false;
}>({
  title: "",
  children: null,
  cb: (ok: boolean) => void ok,
  open: false,
  makeOpen: () => Promise.resolve(false),

  dialogProps: {},
  ok: "Ok",
  cancel: "Cancel",
});

function DialogContextProvider(props: { children: React.ReactNode }) {
  const [title, setTitle] = useState("");
  const [children, setChildren] = useState<React.ReactNode>(null);
  const [open, setOpen] = useState(false);
  const [ok, setOk] = useState<string | false>("Ok");
  const [cancel, setCancel] = useState<string | false>("Cancel");

  const [dialogProps, setDialogProps] = useState<BananasDialogProps>({});

  return (
    <DialogContext.Provider
      value={{
        makeOpen: (title, children, options) => {
          setTitle(title);
          setChildren(children);
          setOpen(true);

          if (options?.ok !== undefined) {
            setOk(options.ok);
          }

          if (options?.cancel !== undefined) {
            setCancel(options.cancel);
          }

          if (options?.dialogProps) {
            setDialogProps(options.dialogProps);
          }

          return new Promise((resolve) => {
            const event = (e: CustomEvent<boolean>) => {
              window.removeEventListener("dialogclick", event as EventListener);
              resolve(e.detail);
            };

            window.addEventListener("dialogclick", event as EventListener);
          });
        },
        title,
        children,
        open,
        cb: (ok) => {
          window.dispatchEvent(new CustomEvent("dialogclick", { detail: ok }));
          setOpen(false);
        },
        dialogProps,
        ok,
        cancel,
      }}
    >
      {props.children}
    </DialogContext.Provider>
  );
}

export function BcomDialog() {
  const ctx = useContext(DialogContext);

  return (
    <Dialog {...ctx.dialogProps} open={ctx.open} sx={{ p: 0, ...ctx.dialogProps.sx }}>
      <DialogContent>
        <DialogTitle>{ctx.title}</DialogTitle>
        <DialogContent>{ctx.children}</DialogContent>
        <DialogActions>
          {ctx.cancel && <Button onClick={() => ctx.cb(false)}>{ctx.cancel}</Button>}
          {ctx.ok && <Button onClick={() => ctx.cb(true)}>{ctx.ok}</Button>}
        </DialogActions>
      </DialogContent>
    </Dialog>
  );
}

export function useDialog() {
  const { makeOpen } = useContext(DialogContext);
  return makeOpen;
}

export default DialogContextProvider;
