import { PDFName, PDFPage, PDFString, PDFDocument } from "pdf-lib";
import { PdfData } from "pdfdataextract";
import { config } from "./config";
import { IGetMetaResponse } from "./types";
import { verifyPDF } from "./lib";
import { formatPdfTime } from "./lib/timeUtils";
import { AppError, GeneralError } from "./lib/errors";
import { isPDF } from "./lib/generalUtils";
class PDFparser {
  readonly document;
  readonly config;

  constructor(document: Buffer) {
    this.document = document;
    this.config = config;
  }

  getPDFMeta = async (): Promise<IGetMetaResponse> => {
    if (!(this.document instanceof Buffer)) {
      throw new AppError("Document is not Buffer");
    }

    if (!isPDF(this.document)) {
      throw new AppError("Only pdf file type is supported");
    }

    try {
      const signaturesMeta = await verifyPDF(this.document);
      const pdfMeta = await PdfData.extract(this.document, config);

      const result = {
        pages: pdfMeta.pages,
        title: pdfMeta.info.Title || "Unknown",
        author: pdfMeta.info.Author || "Unknown",
        creation_date: formatPdfTime(pdfMeta.info.CreationDate),
        mod_date: formatPdfTime(pdfMeta.info.ModDate),
      };

      if (signaturesMeta) {
        result["signatures"] = signaturesMeta.signatures;
        result["expired"] = signaturesMeta.expired;
      }

      return result;
    } catch (error) {
      throw new GeneralError(error);
    }
  };

  insertQrCode = async (
    imgBytes: ArrayBuffer,
    url: string,
    coords: any,
    scaleFactor: number
  ): Promise<ArrayBuffer> => {
    const pdfDoc = await PDFDocument.load(this.document);
    const img = await pdfDoc.embedPng(imgBytes);

    const scaled = img.scale(scaleFactor);

    const pages = pdfDoc.getPages();

    for (let index = 0; index < pages.length; index++) {
      const page = pages[index];

      console.log("dynamic x ", coords[index + 1].x);
      console.log("dynamic y ", coords[index + 1].y);

      console.log("x", page.getWidth() / 2 - scaled.width / 2);
      console.log("y", page.getHeight() / 2 - scaled.height / 2);

      page.drawImage(img, {
        x: page.getWidth() / 2 - scaled.width / 2,
        y: page.getHeight() / 2 - scaled.height / 2,
        width: scaled.width,
        height: scaled.height,
      });

      const link = this.createPageLinkAnnotation(page, url, {
        imgXPos: page.getWidth() / 2 - scaled.width / 2,
        imgYPos: page.getHeight() / 2 - scaled.height / 2,
        imgWidth: scaled.width,
        imagHeight: scaled.height,
      });

      page.node.set(PDFName.of("Annots"), pdfDoc.context.obj([link]));
    }

    const pdfBytes = await pdfDoc.save();

    return pdfBytes;
  };

  private createPageLinkAnnotation = (
    page: PDFPage,
    uri: string,
    { imgXPos, imgYPos, imgWidth, imagHeight }
  ) =>
    page.doc.context.register(
      page.doc.context.obj({
        Type: "Annot",
        Subtype: "Link",
        Rect: [imgXPos, imgYPos, imgXPos + imgWidth, imgYPos + imagHeight],
        A: {
          Type: "Action",
          S: "URI",
          URI: PDFString.of(uri),
        },
      })
    );
}

export default PDFparser;