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

import * as React from "react";
import {css, StyleSheet} from "aphrodite";

import {fontWeights, typeScale} from "./styles/typography";
import linkStyles from "./styles/linkStyles";
import ThemeNameContext, {type Theme} from "./context/ThemeNameContext";
import TextLinkContext from "./TextLinkContext";

/* eslint-disable react/prefer-stateless-function */

type Props = {|
  /** TextLinkAction tags can only wrap strings. If you find this restrictive, contact @theseus. The thought is we want to avoid the temptation for folks to wrap entire apps or components in Link tags, since that usually means a different component should be built. */
  +children: string | React.ChildrenArray<string>,
  +onClick: (e: SyntheticInputEvent<HTMLButtonElement>) => void,
  /** Inverse styles for dark backgrounds. */
  +darkBackground: boolean,
  /** The size of the link which is is a subset of TypeScale's sizes. */
  +scale?: "base" | "subtext" | "title",
  /** The boldness of the link. */
  +weight?: $Keys<typeof fontWeights>,
  /** Select a custom display property depending on how you intend to use the link. */
  +display:
    | "inline"
    | "inline-block"
    | "flex"
    | "block"
    | "inline-flex"
    | "none",
  +disabled: boolean,
|};

/**
 * @short In general, try and use a TextLink, which takes an href not an onClick. TextLinks are more accessible (hovering over them shows the link preview in the browser), and don't require JavaScript. Sometimes, however, you need to have something that looks and feels like a TextLink but takes an onClick. This is rendered as a button, but can be nested in <Text> like a TextLink
 * @brandStatus V2
 * @status Stable
 * @category Interaction
 * @extends React.Component */
class TextLinkAction extends React.PureComponent<Props> {
  static defaultProps: {|
    darkBackground: boolean,
    disabled: boolean,
    display: Props["display"],
    onClick: Props["onClick"],
  |} = {
    darkBackground: false,
    display: "inline-block",
    // onClick is noop by default
    onClick: () => {},
    disabled: false,
  };
  static contextType: React.Context<Theme> = ThemeNameContext;
  context: Theme;

  render(): React.Node {
    const {children, onClick, darkBackground, disabled, display} = this.props;
    const linkStyle = linkStyles(this.context);
    return (
      <TextLinkContext.Consumer>
        {parentStyles => {
          let {scale, weight} = this.props;
          // If we are not provided with a style prop and we will use the one from context
          scale = scale || parentStyles.scale;
          weight = weight || parentStyles.weight;
          return (
            // eslint-disable-next-line react/forbid-elements
            <button
              type="button"
              className={css(
                styles.link,
                styles.standardOverride,
                darkBackground ? linkStyle.inverse : linkStyle.default
              )}
              style={{
                display,
                color: "inherit",
                font: "inherit",
                ...typeScale[scale],
                fontWeight: weight,
              }}
              onClick={onClick}
              disabled={disabled}
            >
              {children}
            </button>
          );
        }}
      </TextLinkContext.Consumer>
    );
  }
}

export default TextLinkAction;

const styles = StyleSheet.create({
  link: {
    background: "none",
    border: "none",
    margin: "0",
    padding: "0",
    cursor: "pointer",
    overflow: "visible",
    lineHeight: "normal",
    width: "auto",
  },
  standardOverride: {
    // override for our questionable OOCSS bottom margins on all semantic type tags
    marginBottom: 0,
    marginTop: 0,
    cursor: "pointer",
  },
});
