import React, { ReactElement, MouseEvent, forwardRef } from 'react';

import Icon, { IconName } from '../Icon';

import { StyledMenuItem, LeftElement, MenuIcon } from './StyledMenu';

export interface MenuItemProps {
  /**
   * Whether this menu item should appear with active state.
   */
  active?: boolean;
  /**
   * Whether this menu item is non-interactive. All event handlers will be ignored.
   */
  disabled?: boolean;
  /**
   * Whether this menu item is on focus.
   */
  focused?: boolean;
  /**
   * Icon name or a custom icon as a react element.
   */
  icon?: IconName | ReactElement;
  /**
   * Visual intent color to apply to menu item.
   */
  intent?: 'text' | 'danger';
  /**
   * Click event handler.
   */
  onClick?: (e: MouseEvent) => void;
  /**
   * Item text to display.
   */
  text: string;
  /**
   * Right-aligned content, useful for displaying hotkeys.
   */
  textElement?: ReactElement;
}

const getThemeState = ({
  disabled,
  active,
  focused,
}: {
  active?: boolean;
  disabled?: boolean;
  focused?: boolean;
}): 'default' | 'disabled' | 'active' | 'focused' => {
  if (disabled === true) {
    return 'disabled';
  }

  if (active === true) {
    return 'active';
  }

  if (focused === true) {
    return 'focused';
  }

  return 'default';
};

const MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(
  (
    {
      text,
      icon,
      intent = 'text',
      active = false,
      disabled = false,
      focused = false,
      textElement,
      onClick,
      ...otherLiAttrs
    }: MenuItemProps,
    forwardedRef
  ): ReactElement => {
    const rightElement = React.isValidElement(textElement) && textElement;

    const themeState = getThemeState({ disabled, active, focused });
    const themeIntent = intent;

    return (
      <StyledMenuItem
        {...otherLiAttrs}
        ref={forwardedRef}
        themeState={themeState}
        themeIntent={themeIntent}
        onClick={onClick}
      >
        <LeftElement>
          {icon !== undefined && (
            <MenuIcon>
              <Icon
                icon={icon}
                intent={disabled === true ? 'subdued-text' : intent}
              />
            </MenuIcon>
          )}
          {text}
        </LeftElement>
        {rightElement}
      </StyledMenuItem>
    );
  }
);

MenuItem.displayName = 'MenuItem';

export default MenuItem;
