import React, { useState, useRef, useEffect } from "react";
import { CopyToClipboard } from "react-copy-to-clipboard";
import { Bubble } from "../bubble";
import { useTranslation } from "../i18n";
import { Icon } from "../icon";
import { injectValue } from "../_util/inject-value";
import { noop } from "../_util/noop";
import { TriggerProps } from "../popover";
import { StyledProps } from "../_type";

export interface CopyProps {
  /**
   * 待复制的文本内容
   */
  text: string;

  /**
   * 复制事件触发回调，其中 `context` 中 `result`：
   *  - `true` 复制成功
   *  - `false` 复制失败
   */
  onCopy?: (text: string, context: { result: boolean }) => void;

  /**
   * 自定义按钮提示
   * @default copied => copied ? "复制成功" : "复制" （已处理国际化）
   */
  tips?: React.ReactNode | ((copied: boolean) => React.ReactNode);

  /**
   * 自定义按钮渲染
   * @default <Icon type="copy" />
   * @docType React.ReactNode | ((copied: boolean) => React.ReactNode)
   */
  children?: React.ReactNode | ((copied: boolean) => React.ReactNode);
}

function HoverTrigger({
  setVisible,
  openDelay = 50,
  closeDelay = 100,
  render,
  onReset,
}: TriggerProps & { onReset: () => void }) {
  const commonProps = {
    onMouseEnter: () => {
      onReset();
      setVisible(true, openDelay);
    },
    onMouseLeave: () => setVisible(false, closeDelay),
  };
  return render({
    overlayProps: commonProps,
    childrenProps: commonProps,
  });
}

HoverTrigger.displayName = "CopyHoverTrigger";

export function Copy(props: CopyProps) {
  const t = useTranslation();
  const {
    text,
    tips = copied => (copied ? t.copied : t.copy),
    onCopy = noop,
    children = <Icon type="copy" />,
  } = props;
  const [copied, setCopied] = useState(false);
  const timerRef = useRef(null);
  useEffect(() => () => clearTimeout(timerRef.current), []);

  const element = injectValue(children)(copied) as React.ReactElement;

  return (
    <Bubble
      trigger={[
        HoverTrigger,
        {
          onReset: () => {
            setCopied(false);
            clearTimeout(timerRef.current);
          },
        },
      ]}
      content={injectValue(tips)(copied)}
    >
      <CopyToClipboard
        text={text}
        onCopy={(text, result) => {
          onCopy(text, { result });
          if (result) {
            if (timerRef.current) {
              clearTimeout(timerRef.current);
            }
            setCopied(true);
            timerRef.current = setTimeout(() => setCopied(false), 1500);
          }
        }}
      >
        {React.isValidElement<StyledProps>(element) ? (
          React.cloneElement(element, {
            style: { cursor: "pointer", ...(element.props.style || {}) },
          })
        ) : (
          <span style={{ cursor: "pointer" }}>{element}</span>
        )}
      </CopyToClipboard>
    </Bubble>
  );
}

Copy.displayName = "Copy";
