import React, { ReactElement, ReactNode } from "react";
import classNames from "classnames";
import { THEME } from "../../types";
import { Avatar, AvatarProps, AvatarSize, AVATAR_TYPE } from "../Avatar";
import { Box } from "../Box";
import { Flex } from "../Flex";
import { Link } from "../Link";
import { MenuRenderer, useMenuContext } from "../MenuRenderer";
import { PopoverMenu } from "../PopoverMenu";
import { Text } from "../Text";
import { AppbarDropdownIcon } from "./AppbarDropdownIcon";
import { AppbarTabMarker } from "./AppbarTabMarker";
import { cn, popperModifiers } from "./config";

type AppbarUserNameProps = {
  avatar: ReactElement<AvatarProps>;
  name?: string;
};

type AppbarUserDropdownProps = {
  avatar: ReactElement<AvatarProps>;
  children: ReactNode;
  name?: string;
  onClose?: () => void;
};

type AppbarUserDropdownMenuProps = {
  children: ReactNode;
};

type AppbarUserProps = {
  avatar: ReactElement<AvatarProps>;
  name?: string;
};

type AppbarUserDropdownMenuItemProps = {
  as?: any;
  onClick?: () => void;
  selected?: boolean;
  [key: string]: any;
};

const AppbarUserName = ({ name, avatar }: AppbarUserNameProps) => (
  <Flex className={cn({ e: "userName" })}>
    {avatar}
    {name && <Text as="div">{name}</Text>}
  </Flex>
);

// Deprecated: Remove this component in v2
export const AppbarUserAvatar = (props: AvatarProps) => {
  const sharedClassNames = "mr-2";
  const sharedProps = {
    size: "medium" as AvatarSize,
    square: true,
  };

  if (props.type === AVATAR_TYPE.SYSTEM) {
    return (
      <Avatar
        className={sharedClassNames}
        type={AVATAR_TYPE.SYSTEM}
        {...sharedProps}
      />
    );
  }

  if (props.type === AVATAR_TYPE.USER && props.email) {
    return (
      <Avatar
        className={sharedClassNames}
        type={AVATAR_TYPE.USER}
        email={props.email}
        {...sharedProps}
      />
    );
  }

  return (
    <Avatar
      className={classNames(sharedClassNames, "bg-gray-400")}
      type={AVATAR_TYPE.ANONYMOUS}
      {...sharedProps}
    />
  );
};

export const AppbarUserDropdown = ({
  name,
  avatar,
  children,
  onClose,
}: AppbarUserDropdownProps) => {
  return (
    <Box className="h-full -mr-3">
      <MenuRenderer
        className={classNames([cn({ e: "menu" }), cn({ e: "userMenu" })])}
        popperModifiers={popperModifiers}
        onClose={onClose}
        trigger={({ onClick, ...triggerProps }, { isOpen }) => (
          <button
            type="button"
            className={classNames([
              cn({ e: "menuButton" }),
              cn({ e: "userMenuButton" }),
              isOpen && "isOpen",
              "hasTabMarker",
            ])}
            {...triggerProps}
            onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
              onClick(event);
              if (onClose && isOpen) {
                onClose();
              }
            }}
          >
            <Flex className="items-center">
              <AppbarUserName name={name} avatar={avatar} />
              <AppbarDropdownIcon />
            </Flex>

            <AppbarTabMarker />
          </button>
        )}
      >
        {({ listProps }) => (
          <PopoverMenu
            className={cn({ e: "menuList" })}
            theme={THEME.BRAND}
            {...listProps}
          >
            {children}
          </PopoverMenu>
        )}
      </MenuRenderer>
    </Box>
  );
};

export const AppbarUserDropdownMenu = ({
  children,
}: AppbarUserDropdownMenuProps) => <>{children}</>;

export const AppbarUserDropdownMenuItem = ({
  children,
  onClick,
  as,
  className,
  ...rest
}: AppbarUserDropdownMenuItemProps) => {
  const { itemProps, onClose } = useMenuContext();
  return (
    <Link
      as={as}
      noStyles
      className={classNames([
        cn({ e: "menuItem" }),
        cn({ e: "userMenuItem" }),
        className,
      ])}
      onClick={() => {
        if (typeof onClick === "function") {
          onClick();
        }
        if (typeof onClose === "function") {
          onClose();
        }
      }}
      {...rest}
      {...itemProps}
    >
      {children}
    </Link>
  );
};

export const AppbarUser = ({ name, avatar }: AppbarUserProps) => {
  return (
    <Box className={cn({ e: "user" })}>
      <AppbarUserName name={name} avatar={avatar} />
    </Box>
  );
};
