import { Canvas, Image, View } from "@tarojs/components";
import Taro, { FC } from "@tarojs/taro";
import { useEffect, useRef, useState } from "react";
import { AtFloatLayout } from "taro-ui";
import { AtFloatLayoutProps } from "taro-ui/types/float-layout";
import CloseIcon from "../../../images/icon_back@2x-min.png";
import "./index.scss";

export interface CertLayoutProps extends AtFloatLayoutProps {
  name: string;
  date: string;
}

const system = Taro.getSystemInfoSync();

export const CertLayout: FC<CertLayoutProps> = ({ name, date, ...props }) => {
  const loaded = useRef(false);
  const [imgPath, setImgPath] = useState("");

  useEffect(() => {
    if (props.isOpened && !loaded.current) init();
  }, [props.isOpened]);

  const init = async () => {
    try {
      Taro.showLoading({
        title: "绘制中",
      });

      await new Promise((resolve, reject) => {
        Taro.createSelectorQuery()
          .select("#certCanvas")
          .fields({ node: true, size: true }, async (res) => {
            const canvas = res.node;
            const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;

            canvas.width = res.width * system.pixelRatio;
            canvas.height = res.height * system.pixelRatio;

            try {
              const bgInfo = await getTempImgPath(
                "https://wuxicharitymuseum.cn/wx-csbwg-public/images/cert-min.png"
              );
              const ratio = bgInfo.width / canvas.width;

              const bgSource = await loadImg(canvas, bgInfo.path);

              ctx.drawImage(bgSource, 0, 0, canvas.width, canvas.height);

              ctxText(
                ctx,
                "特此授予锡善云城·热心市民".split("").join(" "),
                `${7 * system.pixelRatio}px SourceHanSansSCRegular`,
                "center",
                "#424A4A",
                canvas.width / 2,
                800 / ratio
              );

              ctxText(
                ctx,
                name.split("").join(" "),
                `${15 * system.pixelRatio}px SourceHanSansCN-Bold`,
                "center",
                "#CFC49E",
                canvas.width / 2,
                1020 / ratio
              );

              ctxTextWrap(
                ctx,
                "特此证明，感谢您的热情参与与慷慨支持。您的善举为社区带来了无限的温暖与希望。因您的无私奉献，特授予您热心市民称号，以表彰您对慈善事业的贡献。您的善行将永远激励着我们，为构建更美好的社会贡献一份力量。",
                `${7 * system.pixelRatio}px SourceHanSansSCRegular`,
                "center",
                "#424A4A",
                canvas.width / 2,
                1200 / ratio,
                460 * system.pixelRatio
              );

              ctxText(
                ctx,
                date,
                `${6 * system.pixelRatio}px SourceHanSerifCN-Bold`,
                "left",
                "#424A4A",
                740 / ratio,
                1660 / ratio
              );

              ctxText(
                ctx,
                "锡善云城",
                `${6 * system.pixelRatio}px SourceHanSerifCN-Bold`,
                "left",
                "#424A4A",
                1880 / ratio,
                1660 / ratio
              );

              await new Promise((resolve, reject) => {
                Taro.canvasToTempFilePath({
                  canvas,
                  fileType: "jpg",
                  success(res2) {
                    setImgPath(res2.tempFilePath);

                    loaded.current = true;
                    resolve(true);
                  },
                  fail(err) {
                    Taro.showToast({
                      title: err.errMsg,
                      icon: "none",
                      duration: 4000,
                    });
                    reject(err);
                  },
                });
              });

              resolve(true);
            } catch (err) {
              reject(false);
            }
          })
          .exec();
      });
    } finally {
      Taro.hideLoading();
    }
  };

  const loadImg = (canvas, src) => {
    return new Promise((res, rej) => {
      const source = canvas.createImage();
      source.src = src;
      source.onload = () => {
        res(source);
      };
      source.onerror = rej;
    }) as Promise<CanvasImageSource>;
  };

  const ctxTextWrap = (ctx, text, font, align, color, x, y, maxWidth) => {
    let line = "";
    const lines: string[] = [];
    const words = text.split("");
    for (let i = 0; i < words.length; i++) {
      const word = words[i];
      const testLine = line + word;
      const metrics = ctx.measureText(testLine);

      if (metrics.width > maxWidth && i > 0) {
        lines.push(line);
        line = word;
      } else {
        line = testLine;
      }
    }
    lines.push(line);

    lines.forEach((t, idx) =>
      ctxText(ctx, t, font, align, color, x, y + idx * 28)
    );
  };

  const ctxText = (ctx, text, font, align, color, x, y) => {
    ctx.beginPath();
    ctx.font = font;
    ctx.textAlign = align;
    ctx.fillStyle = color;
    ctx.fillText(text, x, y);
    ctx.save();
  };

  const getTempImgPath = async (src: string) => {
    return new Promise((resolve, reject) => {
      Taro.getImageInfo({
        src,
        success(res) {
          resolve(res);
        },
        fail(err) {
          reject(err);
        },
      });
    }) as Promise<Taro.getImageInfo.SuccessCallbackResult>;
  };

  return (
    <AtFloatLayout className="cert" {...props}>
      <View className="cert-wrap">
        {imgPath ? (
          <>
            <Image
              className="cert__img"
              src={imgPath}
              showMenuByLongpress
              onClick={() => {
                Taro.previewImage({
                  current: imgPath,
                  urls: [imgPath],
                });
              }}
            />

            <View className="cert__tips">长按图片，保存证书</View>
          </>
        ) : (
          <Canvas
            id="certCanvas"
            type="2d"
            className="cert__img"
            style="position:absolute; top: -200%; left: -200%"
          />
        )}
      </View>

      <Image className="cert__close" src={CloseIcon} onClick={props.onClose} />
    </AtFloatLayout>
  );
};
