/**
 * TEAM: frontend_infra
 *
 * @flow strict
 */

/* eslint-disable flexport/no-unused-aphrodite-styles */
import * as React from "react";
import {css} from "aphrodite";
import {createThemedStylesheet, type ThemeData} from "./styles";
import ThemeNameContext, {
  TRANSMISSION,
  type Theme,
} from "./context/ThemeNameContext";
import latitudeColors, {transmissionColors} from "./colors";
import Text from "./Text";
import {type StatusIntent} from "./Status";

type Props = {|
  /** Value determines when the badge is rendered and how. If either false, 0 or undefined the badge is not rendered. If true, the badge is rendered as a dot. If a number greater than 0, the badge is rendered with the number inside */
  +value?: number | boolean,
  /** The maximum value to be displayed. Any value larger will be shown as this number followed by a plus sign */
  +max?: number,
  /** The intent of the badge determines the background color */
  +intent?: StatusIntent,
  /** Component wrapped by the badge. If there is one, the badge is rendered on the top right corner */
  +children?: React.Node,
|};

export const DOT_BADGE_SIZE = 12;

/**
 * @category General
 * @short The badge is a component displaying the number of items await your attention.
 * @brandStatus V3
 * @status Beta
 * The badge component informs the user that a certain element on the page has
 * new information for the user. A value can be provided to indicate exactly
 * how many new items there are. If a child is provided, the badge will render
 * to the top right of the child.
 */
export default function Badge({
  value,
  max = 99,
  intent = "active",
  children = null,
}: Props): React.Node {
  const theme = React.useContext(ThemeNameContext);
  const styles = getStyle(theme);

  // Either undefined, false or 0
  if (value == null || value === false || value === 0) {
    return children;
  }

  const isStatusDot = value === true && !children;
  const badge = (
    <div
      className={css(
        styles[intent],
        value === true ? styles.dotBadge : styles.badge,
        isStatusDot && styles.statusDot
      )}
    >
      {typeof value === "number" && (
        <Text color={getTextColor(intent)} scale="subtext">
          {value <= max ? value : `${max}+`}
        </Text>
      )}
    </div>
  );

  return children === null ? (
    badge
  ) : (
    <div className={css(styles.badgeBase)}>
      {children}
      <div className={css(styles.badgeWrapper)}>{badge}</div>
    </div>
  );
}

function getTextColor(intent: StatusIntent) {
  if (intent === "complete" || intent === "pending") {
    return "grey60";
  }
  return "white";
}

function getThemeColors(themeName: Theme) {
  if (themeName === TRANSMISSION) {
    return {
      active: transmissionColors.green40,
    };
  }
  return {
    active: latitudeColors.indigo30,
  };
}

const getStyle = createThemedStylesheet(({themeName}: ThemeData) => {
  const themeColors = getThemeColors(themeName);
  return {
    badgeBase: {
      display: "inline-block",
      position: "relative",
    },
    badgeWrapper: {
      position: "absolute",
      pointerEvents: "none",
      top: 0,
      right: 0,
      transform: "translateX(50%) translateY(-50%)",
    },
    active: {
      backgroundColor: themeColors.active,
    },
    complete: {
      backgroundColor: latitudeColors.green40,
      color: latitudeColors.grey60,
    },
    pending: {
      backgroundColor: latitudeColors.grey30,
    },
    error: {
      backgroundColor: latitudeColors.red40,
    },
    done: {
      backgroundColor: latitudeColors.black,
    },
    "due-soon": {
      backgroundColor: latitudeColors.orange30,
    },
    badge: {
      display: "flex",
      justifyContent: "center",
      minWidth: 20,
      borderRadius: 20,
      padding: "2px 5px",
    },
    dotBadge: {
      display: "block",
      borderRadius: 100,
      height: 8,
      width: 8,
    },
    statusDot: {
      height: DOT_BADGE_SIZE,
      minWidth: DOT_BADGE_SIZE,
    },
  };
});
