import React, { forwardRef, ForwardRefExoticComponent } from "react";
import classNames from "classnames";
import { Box, BoxProps } from "../Box";
import { bem } from "../../utilities/bem";
import { ICON_STYLE_PREFIX, Icon, ICON_TYPE } from "../Icon";
import { STATUS_VARIANT } from "../../types";
import { Badge, BADGE_SIZE } from "../Badge";

const cn = "Reference";

export interface ReferenceProps {
  as?: any;
  disabled?: boolean;
  icon?: ICON_TYPE;
  iconPrefix?: ICON_STYLE_PREFIX;
  badgeVariant?: STATUS_VARIANT;
  badgeLabel?: string;
  /**
   * Used to disable interactive (i.e. hover) styles when the `Reference`
   * is not a link or button
   */
  noLink?: boolean;
  [key: string]: any;
}

export type ReferenceWithReferenceGroup = ForwardRefExoticComponent<ReferenceProps> & {
  Group: (props: BoxProps) => JSX.Element;
};

const ReferenceGroup = ({ className, ...rest }: BoxProps) => (
  <Box className={classNames(bem(`${cn}Group`), className)} {...rest} />
);

export const Reference = forwardRef<HTMLElement, ReferenceProps>(
  (
    {
      as: Component = "a",
      disabled,
      className,
      icon,
      iconPrefix,
      badgeVariant,
      badgeLabel,
      children,
      target,
      noLink,
      ...rest
    },
    ref,
  ) => (
    <Component
      className={classNames(
        bem(cn),
        !noLink && bem(cn, { m: "isLink" }),
        disabled && bem(cn, { m: "disabled" }),
        className,
      )}
      disabled={Component === "button" && disabled}
      target={target}
      rel={`${target === "_blank" ? "noopener noreferrer" : ""}`}
      ref={ref}
      {...rest}
    >
      {icon && (
        <Box>
          <Icon
            className={classNames(bem(cn, { e: "icon" }))}
            icon={icon}
            prefix={iconPrefix}
          />
        </Box>
      )}
      {children}
      {badgeLabel && (
        <Badge
          className={classNames(bem(cn, { e: "badge" }))}
          variant={badgeVariant}
          size={BADGE_SIZE.MICRO}
        >
          {badgeLabel}
        </Badge>
      )}
    </Component>
  ),
) as ReferenceWithReferenceGroup;

Reference.Group = ReferenceGroup;
