import {
  fontkit,
  PDFDocument,
  PDFName,
  PDFPage,
  PDFRef,
  PDFString,
  rgb,
  shuffle,
} from "./deps.ts";
import { JSONType, Voca } from "../types.ts";

function downloadBuffer(buffer: Uint8Array, fileName: string) {
  const a: HTMLAnchorElement = document.createElement("a");
  const blob = new Blob([buffer], { type: "application/octet-stream" });

  a.href = URL.createObjectURL(blob);
  a.download = fileName;
  document.body.appendChild(a);
  a.style.display = "none";
  a.click();
  a.remove();
}

export async function makePdf(voca_list: Voca[]) {
  const pdfDoc = await PDFDocument.create();

  const fontBytes = await fetch("./NanumGothic.ttf").then((res) =>
    res.arrayBuffer()
  );
  pdfDoc.registerFontkit(fontkit);
  const customFont = await pdfDoc.embedFont(fontBytes);

  const fontSize = 12;
  const margin = 20;
  const perColumn = 25;
  const perPage = 50;

  let page!: PDFPage;
  let col = -1;
  let yCursor = 1;
  let pdfUrlList: PDFRef[] = [];

  // 문제 생성
  for (let i = 0; i < voca_list.length; ++i) {
    const data = voca_list[i];
    if (i % perPage === 0) {
      if (page) {
        page.node.set(PDFName.of("Annots"), pdfDoc.context.obj(pdfUrlList));
      }
      pdfUrlList = [];
      page = pdfDoc.addPage();

      yCursor = 1;
      col = -1;
    }
    if (i % perColumn === 0) {
      col++;
      yCursor = 1;
    }

    const text = `${i + 1}. ${data.word}`;
    const textWidth = customFont.widthOfTextAtSize(text, fontSize);
    const textHeight = customFont.heightAtSize(fontSize);
    const textX = margin + (page.getWidth() / 2) * col;
    const textY = page.getHeight() - (fontSize + margin) * yCursor;

    const pdfUrlDict = pdfDoc.context.obj({
      Type: "Annot",
      Subtype: "Link",
      Rect: [textX, textY, textX + textWidth, textY + textHeight],
      A: {
        Type: "Action",
        S: "URI",
        URI: PDFString.of(
          `https://en.dict.naver.com/#/search?range=all&query=${
            encodeURIComponent(data.word)
          }`,
        ),
      },
    });
    const pdfUrl = pdfDoc.context.register(pdfUrlDict);
    pdfUrlList.push(pdfUrl);

    page.drawText(text, {
      x: textX,
      y: textY,
      size: fontSize,
      font: customFont,
      color: rgb(0, 0, 0),
    });
    page.drawText("_________________", {
      x: margin + (page.getWidth() / 2) * col + 140,
      y: page.getHeight() - (fontSize + margin) * yCursor - 3,
      size: fontSize,
      font: customFont,
      color: rgb(0, 0, 0),
    });
    yCursor++;
  }

  // 답 생성
  for (let i = 0; i < voca_list.length; ++i) {
    const data = voca_list[i];
    if (i % perPage === 0) {
      if (page) {
        page.node.set(PDFName.of("Annots"), pdfDoc.context.obj(pdfUrlList));
      }
      pdfUrlList = [];
      page = pdfDoc.addPage();
      yCursor = 1;
      col = -1;
    }
    if (i % perColumn === 0) {
      col++;
      yCursor = 1;
    }

    const text = `${i + 1}. ${data.word}`;
    const textWidth = customFont.widthOfTextAtSize(text, fontSize);
    const textHeight = customFont.heightAtSize(fontSize);
    const textX = margin + (page.getWidth() / 2) * col;
    const textY = page.getHeight() - (fontSize + margin) * yCursor;

    const pdfUrlDict = pdfDoc.context.obj({
      Type: "Annot",
      Subtype: "Link",
      Rect: [textX, textY, textX + textWidth, textY + textHeight],
      A: {
        Type: "Action",
        S: "URI",
        URI: PDFString.of(
          `https://en.dict.naver.com/#/search?range=all&query=${
            encodeURIComponent(data.word)
          }`,
        ),
      },
    });
    const pdfUrl = pdfDoc.context.register(pdfUrlDict);
    pdfUrlList.push(pdfUrl);

    page.drawText(text, {
      x: textX,
      y: textY,
      size: fontSize,
      font: customFont,
      color: rgb(0, 0, 0),
    });
    page.drawText("_________________", {
      x: margin + (page.getWidth() / 2) * col + 140,
      y: page.getHeight() - (fontSize + margin) * yCursor - 3,
      size: fontSize,
      font: customFont,
      color: rgb(0, 0, 0),
    });
    page.drawText(data.answer, {
      x: margin + (page.getWidth() / 2) * col + 140,
      y: page.getHeight() - (fontSize + margin) * yCursor,
      size: 8,
      font: customFont,
      color: rgb(1, 0, 0),
    });
    yCursor++;
  }

  const pdfBytes = await pdfDoc.save();
  return pdfBytes;
}

export async function downloadVocaQuiz(levels: number[], day: number) {
  if (levels.includes(10)) levels = [6, 7, 8, 9];
  const json: JSONType = await (await fetch("/voca.json")).json();
  const voca_list = json.data.filter((chunk) =>
    levels.includes(chunk.level) && chunk.day === day
  ).flatMap((chunk) => chunk.voca_list);
  const bufferPdf = await makePdf(shuffle(voca_list));
  downloadBuffer(bufferPdf, `voca-${day}-${levels.join(",")}.pdf`);
}
