import { useRef, useEffect, useMemo, useState } from 'react';
import QRCodeStyling from '@solana/qr-code-styling';
import { Box } from '@mui/material';

type QRCodeStylingOptions = NonNullable<ConstructorParameters<typeof QRCodeStyling>[0]>;

const defaults: QRCodeStylingOptions = {
  margin: 0,
  dotsOptions: {
    type: 'dots',
  },
  cornersSquareOptions: {
    type: 'extra-rounded',
  },
  cornersDotOptions: {
    type: 'dot',
  },
};

export interface QRCodeProps {
  /** 一般情况下仅使用 data/size/image 即可 */
  data: string;
  size: number;
  image?: string;
  /** 覆盖 qr-code-styling 配置 */
  config?: QRCodeStylingOptions;
}

// 该组件用于生成与 android wallet 样式风格相似的 qrcode
// 注意: 依赖的 @solana/qr-code-styling 是一份 fork 版本, 原版本的 margin 配置存在 bug
function QRCode({ data, size, image = undefined, config = {}, ...rest }: QRCodeProps) {
  const ref = useRef(null);
  const options = useMemo(() => {
    return {
      ...defaults,
      data,
      width: size,
      height: size,
      ...(image && {
        image,
        imageOptions: {
          crossOrigin: 'anonymous',
          margin: 0,
        },
      }),
      ...config,
    };
  }, [data, size, image, config]);

  const [qrCode] = useState(new QRCodeStyling(options));

  useEffect(() => {
    if (ref.current) {
      qrCode.append(ref.current);
    }
  }, [qrCode, ref]);

  useEffect(() => {
    if (!qrCode) return;
    qrCode.update(options);
  }, [options, qrCode]);

  return <Box ref={ref} {...rest} />;
}

export default QRCode;
