import '@fontsource/ubuntu-mono/400.css';
import { Check as CheckIcon } from '@mui/icons-material';
import { Box, BoxProps, Tooltip } from '@mui/material';
import copy from 'copy-to-clipboard';
import noop from 'lodash/noop';
import CopyIcon from '@arcblock/icons/lib/Copy';
import React, { ReactNode, useImperativeHandle, useRef, useState } from 'react';
import { styled } from '../Theme';
import { getFontSize } from '../Util';
import CompactText from './compact-text';
import type { Locale, Translations } from '../type';

const translations: Translations = {
  en: {
    copy: 'Click To Copy',
    copied: 'Copied!',
  },
  zh: {
    copy: '点击复制',
    copied: '已复制!',
  },
};

export interface HTMLDidAddressElement extends HTMLDivElement {
  copy: () => void;
  getEl: () => HTMLDivElement;
}
export interface IDidAddressProps extends BoxProps {
  component?: React.ElementType;
  size?: number;
  copyable?: true | false;
  // compact mode 下, hover 时会在 tooltip 中显示完整地址, showCopyButtonInTooltip = true 时会在完整地址后显示一个复制按钮
  showCopyButtonInTooltip?: false | true;
  content?: string;
  inline?: false | true;
  prepend?: ReactNode;
  append?: ReactNode;
  // 紧凑模式
  compact?: false | true;
  startChars?: number;
  endChars?: number;
  locale?: Locale;
}

/**
 * DidAddress 组件 (新版设计)
 *
 * - 样式调整
 * - click-to-copy 调整
 * - 长文本截断处理 (Ellipsis)
 * - 支持 inline 或 block 的显示方式
 * - 支持紧凑模式, 该模式下:
 *   - 占用宽度较小, 因此不考虑水平空间不够用的情况, 且忽略末尾省略号
 *   - 对于多层元素结构的 children, 保持元素结构, 将最内层 text 替换为 CompactText 组件
 *   - 为保证 copy 功能正常工作, 原 children 始终渲染, 但在紧凑式下会隐藏
 *   - 可配合 useMediaQuery 使用
 */
function DidAddress({
  ref = undefined,
  ...props
}: IDidAddressProps & {
  ref?: React.Ref<unknown>;
}) {
  const {
    component = 'span',
    size = 0,
    copyable = true,
    showCopyButtonInTooltip = false,
    children = null,
    content = '',
    prepend = null,
    append = null,
    compact = false,
    startChars = 6,
    endChars = 6,
    locale: originalLocale = 'en',
    ...rest
  } = props;
  let locale = originalLocale;
  if (!translations[locale]) {
    locale = 'en';
  }

  const [copied, setCopied] = useState(false);
  const textRef = useRef<HTMLDivElement>(null);
  const rootRef = useRef<any>(null);

  const handleCopy = () => {
    copy(content || textRef.current?.textContent || '');
    setCopied(true);
    // 恢复 copied 状态
    setTimeout(() => {
      setCopied(false);
    }, 1500);
  };
  const onCopy = (e: any) => {
    e.stopPropagation();
    e.preventDefault();
    handleCopy();
  };
  useImperativeHandle(
    ref,
    () =>
      new Proxy(
        {
          copy: handleCopy,
          getEl: () => rootRef.current,
        },
        {
          get(target: any, key: string) {
            return target[key] || rootRef.current?.[key];
          },
        }
      )
  );

  let copyElement = null;
  if (copyable) {
    copyElement = (
      <span className="did-address-copy-wrapper" title={copied ? '' : translations[locale].copy}>
        {copied ? (
          <Tooltip title={translations[locale].copied} placement="bottom" arrow open={copied}>
            <CheckIcon className="did-address-copy" sx={{ color: 'success.main' }} />
          </Tooltip>
        ) : (
          /* title prop 直接加在 icon 上不生效 */
          <CopyIcon className="did-address-copy" width="1em" height="1em" onClick={onCopy} />
        )}
      </span>
    );
  }

  return (
    <Root as={component} size={size} {...rest} ref={rootRef}>
      {prepend}
      <Box sx={{ display: 'none' }} ref={textRef}>
        {children}
      </Box>
      {/* 注意: 该元素必须渲染(可以隐藏), 以便 compact 模式下复制的文本是完整的 */}
      <Tooltip title={copyable ? '' : translations[locale].copied} placement="bottom" arrow open={copied}>
        {compact ? (
          <Box
            component="span"
            className="did-address-text"
            sx={{
              cursor: copyable ? 'unset' : 'pointer',
            }}
            onDoubleClick={copyable ? noop : onCopy}>
            <CompactText startChars={startChars} endChars={endChars} showCopyButtonInTooltip={showCopyButtonInTooltip}>
              {children}
            </CompactText>
          </Box>
        ) : (
          <Box
            component="span"
            className="did-address-text did-address-truncate"
            sx={{
              display: compact ? 'none' : 'inline',
              cursor: copyable ? 'unset' : 'pointer',
            }}
            onDoubleClick={copyable ? noop : onCopy}>
            {children}
          </Box>
        )}
      </Tooltip>
      {copyElement}
      {append}
    </Root>
  );
}

export default DidAddress;

const Root = styled<any>(Box, { shouldForwardProp: (prop) => prop !== 'inline' })`
  font-family: 'Ubuntu Mono', monospace;
  && {
    display: ${({ inline }: any) => (inline ? 'inline-flex' : 'flex')};
    align-items: center;
    max-width: 100%;
    overflow: hidden;
    color: #ccc;
    font-size: ${(props: any) => getFontSize(props.size)};
    font-weight: 400;

    svg {
      fill: currentColor;
    }
  }

  .did-address-text {
    color: ${({ theme }) => theme.palette.text.secondary};
  }
  /* truncate string with ellipsis */
  .did-address-truncate {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .did-address-copy-wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 1em;
    height: 1em;
    margin-left: 8px;
  }
  .did-address-copy {
    flex: 0 0 auto;
    font-size: 1em;
    color: ${({ theme }) => theme.palette.text.secondary};
    cursor: pointer;
  }

  /* link */
  a {
    color: ${({ theme }) => theme.palette.text.secondary};
  }
  &:hover a {
    color: ${({ theme }) => theme.palette.text.primary};
    text-decoration: underline;
  }
`;
