import React from "react";
import { Menu as MUIMenu, MenuProps as MUIMenuProps } from "@mui/material";

import { twMerge } from "../../../tailwind.config";
import { MenuItem } from "./MenuItem";
import { MenuDivider } from "./MenuDivider";
import { MenuCheckboxItem } from "./MenuCheckboxItem";

export interface MenuProps extends Omit<MUIMenuProps, "open" | "className"> {
  anchorEl: HTMLElement | null;
  placement?:
    | "top"
    | "top-start"
    | "top-end"
    | "bottom"
    | "bottom-start"
    | "bottom-end";
  spacing?: "4" | "6" | "8" | "12" | "16";
  ESCAPE_className?: string;
  ESCAPE_paperClassName?: string;
}

type Alignment = "start" | "end";

export const paperStyles = "shadow-S300 rounded-12 p-8 box-border";

export const Menu = ({
  children,
  anchorEl,
  placement = "bottom-end",
  spacing = "16",
  ESCAPE_className,
  ESCAPE_paperClassName,
  ...restProps
}: MenuProps) => {
  if (!anchorEl) return null;

  const anchorRect = anchorEl.getBoundingClientRect();
  const alignment = placement.split("-")[1] as Alignment;
  const leftValues = {
    start: anchorRect.right,
    end: anchorRect.left,
  };
  const anchorPosition = {
    left: leftValues[alignment] || anchorRect.width / 2 + anchorRect.left,
    top: placement.includes("top")
      ? anchorRect.top - +spacing
      : anchorRect.bottom + +spacing,
  };
  const horizontalPosition =
    alignment === "start" ? "right" : alignment === "end" ? "left" : "center";

  return (
    <MUIMenu
      classes={{
        root: ESCAPE_className,
        paper: twMerge(paperStyles, ESCAPE_paperClassName),
        list: "p-0 box-border",
      }}
      transformOrigin={{
        horizontal: horizontalPosition,
        vertical: placement.includes("top") ? "bottom" : "top",
      }}
      anchorPosition={anchorPosition}
      anchorReference="anchorPosition"
      open={Boolean(anchorEl)}
      anchorEl={anchorEl}
      marginThreshold={8}
      {...restProps}
    >
      {children}
    </MUIMenu>
  );
};

Menu.Item = MenuItem;
Menu.CheckboxItem = MenuCheckboxItem;
Menu.Divider = MenuDivider;
