import React, { forwardRef, Ref } from "react";
import classNames from "classnames";
import { Tooltip } from "../tooltip";
import { StyledProps } from "../_type";
import { useConfig } from "../_util/config-context";
import { CopyProps, Copy } from "../copy";

/**
 * 支持当前 `parent` 标签原生支持的属性
 */
export interface TextProps<P extends keyof JSX.IntrinsicElements>
  extends StyledProps {
  /**
   * 使用什么标签来渲染文本，对应标签原生属性可透传至组件
   * @default span
   */
  parent?: P;

  /**
   * 文本的水平居中方式
   */
  align?: "left" | "center" | "right" | "justify";

  /**
   * 文本的垂直居中方式
   */
  verticalAlign?:
    | "baseline"
    | "top"
    | "middle"
    | "bottom"
    | "text-top"
    | "text-bottom";

  /**
   * 指定 `overflow` 为 `true` 对文本进行单行溢出控制，宽度溢出的文本会以 ... 显示
   */
  overflow?: boolean;

  /**
   * 指定 `nowrap` 为 `true` 强制文本不换行，超长溢出
   */
  nowrap?: boolean;

  /**
   * 指定 `underline` 为 `true` 显示虚下划线
   */
  underline?: boolean;

  /**
   * 内容所使用的 `tooltip`
   *
   * - 2.7.0 支持传递 `true`，将默认使用文字内容
   */
  tooltip?: boolean | React.ReactNode;

  /**
   * 文本的颜色主题
   */
  theme?:
    | "text"
    | "label"
    | "weak"
    | "strong"
    | "primary"
    | "success"
    | "warning"
    | "danger"
    | "cost";

  /**
   * 文本的背景颜色主题
   */
  bgTheme?: "success" | "warning" | "danger";

  /**
   * 文本浮动方式，配置 `clear` 以清除浮动
   */
  float?: "left" | "right" | "clear";

  /**
   * 重置文字 fontSize
   *
   * @default false
   */
  reset?: boolean;

  /**
   * 文本内容
   */
  children?: React.ReactNode;

  /**
   * 是否支持复制
   */
  copyable?: boolean | CopyProps;
}

export type TextPropsType<
  P extends keyof JSX.IntrinsicElements
> = JSX.IntrinsicElements[P] & TextProps<P>;

function TextRaw<P extends keyof JSX.IntrinsicElements = "span">(
  props: TextPropsType<P>,
  ref: Ref<JSX.IntrinsicElements[P]>
) {
  const { classPrefix } = useConfig();
  const {
    parent,
    align,
    verticalAlign,
    overflow,
    nowrap,
    underline,
    tooltip,
    className,
    style,
    theme,
    bgTheme,
    float,
    reset,
    copyable,
    ...htmlProps
  } = props;

  const { children: rawChildren } = props;

  let children = rawChildren;
  if (copyable && !overflow) {
    const copyProps = typeof copyable === "object" ? copyable : {};
    children = (
      <>
        {children} <Copy text={children as string} {...copyProps} />
      </>
    );
  }

  let element: JSX.Element = React.createElement(
    parent || "span",
    {
      ref,
      className: classNames(className, {
        [`${classPrefix}-bg-${bgTheme}`]: bgTheme,
        [`${classPrefix}-text`]: theme === "text",
        [`${classPrefix}-text-${theme}`]: theme && theme !== "text",
        [`${classPrefix}-text-${align}`]: align,
        [`${classPrefix}-align-${verticalAlign}`]: verticalAlign,
        [`${classPrefix}-text-overflow`]: overflow,
        [`${classPrefix}-text-nowrap`]: nowrap,
        [`${classPrefix}-text-underline`]: underline,
        [`${classPrefix}-float-${float}`]: float && float !== "clear",
        [`${classPrefix}-fz-reset`]: reset,
        [`clearfix`]: float === "clear",
      }),
      style,
      ...htmlProps,
    },
    children
  );

  if (copyable && overflow) {
    const copyProps = typeof copyable === "object" ? copyable : {};
    element = React.createElement(
      parent || "span",
      {
        style: { display: "flex" },
      },
      <>
        {element}
        <span style={{ flexShrink: 0 }}>
          <Copy text={children as string} {...copyProps} />
        </span>
      </>
    );
  }

  // 提供快捷 tooltip 使用方式
  if (tooltip) {
    const title = typeof tooltip === "boolean" ? rawChildren : tooltip;
    element = <Tooltip title={title}>{element}</Tooltip>;
  }

  return element;
}

export const Text = (forwardRef(TextRaw) as any) as typeof TextRaw;

(Text as any).displayName = "Text";
