// import { PDFName, PDFPage, PDFString, PDFDocument, PDFImage } from "pdf-lib";
import { nopodofo as npdf, NPDFImageFormat } from "nopodofo";
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";
import {
  getSignatureField,
  pdf,
  sign,
  TimestampAndEnableLTV,
  write,
} from "./utils";
import axios from "axios";
import {
  createWriterToModify,
  PDFPageModifier,
  PDFRStreamForBuffer,
  PDFWStreamForBuffer,
} from "hummus";
import Stream from "pdf-lib/cjs/core/streams/Stream";
import {
  asPDFName,
  degrees,
  drawImage,
  drawRectangle,
  drawText,
  PDFContentStream,
  PDFDocument,
  PDFName,
  PDFOperator,
  PDFOperatorNames,
  PDFPage,
  PDFString,
  popGraphicsState,
  pushGraphicsState,
  rgb,
  rotateDegrees,
  translate,
} from "pdf-lib";
const { Readable } = require("stream");
const streams = require("memory-streams");
import signer from "node-signpdf";
import fs from "fs";
import { PDFNet } from "@pdftron/pdfnet-node";
// const { PDFNet } = require("@pdftron/pdfnet-node");

type SealCoords = {
  [key: string]: { x: string; y: string };
};

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: SealCoords,
    scaleFactor: number
  ): Promise<ArrayBuffer> => {
    // tron pdf library start
    // PDFNet.initialize(licenseKey);
    await PDFNet.initialize(
      "demo:1652778685773:7b893c000300000000b9c455b21b7b47780dc82f9ef63ddc54ce5c282b"
    );
    const input_path = `${__dirname}`;

    // try {
    //   const doc = await PDFNet.PDFDoc.createFromBuffer(this.document);
    //   doc.initSecurityHandler();
    //   const approval_signature_field = await doc.createDigitalSignatureField(
    //     "PDFTronApprovalSig"
    //   );
    //   const widgetAnnotApproval =
    //     await PDFNet.SignatureWidget.createWithDigitalSignatureField(
    //       doc,
    //       new PDFNet.Rect(300, 287, 376, 306),
    //       approval_signature_field
    //     );
    //   const page1 = await doc.getPage(1);
    //   await page1.annotPushBack(widgetAnnotApproval);
    //   await doc.save(
    //     output_path + "abc.pdf",
    //     PDFNet.SDFDoc.SaveOptions.e_remove_unused
    //   );
    // } catch (err) {
    //   console.log(err);
    // }

    const buf = await TimestampAndEnableLTV(
      this.document,
      `${__dirname}/GlobalSignRootForTST.cer`,
      imgBytes
    );

    return buf;
    // try {
    //   if (
    //     !(await TimestampAndEnableLTV(
    //       this.document,
    //       input_path + "GlobalSignRootForTST.cer",
    //       input_path + "qrcode.png",
    //       output_path + "abc_LTV.pdf"
    //     ))
    //   ) {
    //     console.log("fail");
    //   }
    // } catch (error) {
    //   console.log(error);
    // }

    // tron pdf library end

    // lib-pdf signature start
    // const pdfDoc = await PDFDocument.load(this.document);
    // const pdfLibSigImg = await pdfDoc.embedPng(imgBytes);
    // const pdfLibSigImgName = "PDF_LIB_SIG_IMG";
    // const form = pdfDoc.getForm();
    // const sig = form.getSignature("Signature1");
    // sig.acroField.getWidgets().forEach((widget) => {
    //   const { context } = widget.dict;
    //   const { width, height } = widget.getRectangle();
    //   const appearance = [
    //     ...drawRectangle({
    //       x: 100,
    //       y: 0,
    //       width,
    //       height,
    //       borderWidth: 1,
    //       color: rgb(1, 0, 0),
    //       borderColor: rgb(1, 0.5, 0.75),
    //       rotate: degrees(0),
    //       xSkew: degrees(0),
    //       ySkew: degrees(0),
    //     }),
    //     ...drawImage(pdfLibSigImgName, {
    //       x: 100,
    //       y: 5,
    //       width: width - 10,
    //       height: height - 10,
    //       rotate: degrees(0),
    //       xSkew: degrees(0),
    //       ySkew: degrees(0),
    //     }),
    //   ];
    //   const stream = context.formXObject(appearance, {
    //     Resources: { XObject: { [pdfLibSigImgName]: pdfLibSigImg.ref } },
    //     BBox: context.obj([0, 0, width, height]),
    //     Matrix: context.obj([1, 0, 0, 1, 0, 0]),
    //   });
    //   const streamRef = context.register(stream);
    //   widget.setNormalAppearance(streamRef);
    // });
    // const pdfBytes = await pdfDoc.save();
    // const signatureAppearanceStreamRef = this.imageAppearanceStream();
    // pdfDoc.context.obj({
    //   Type: "Annot",
    //   Subtype: "Widget",
    //   FT: "Sig",
    //   Rect: [image.width, image.height, 0, 0],
    //   V: signatureDictRef,
    //   T: PDFString.of("Signature1"),
    //   F: 4,
    //   P: pages[pages.length - 1].ref, //lastPage
    //   AP: pdfDoc.context.obj({ N: signatureAppearanceStreamRef }),
    // });
    // for (let index = 0; index < pages.length; index++) {
    //   const page = pages[index];
    //   const x =
    //     typeof coords[index + 1] !== "undefined"
    //       ? parseFloat(coords[index + 1].x)
    //       : null;
    //   const y =
    //     typeof coords[index + 1] !== "undefined"
    //       ? parseFloat(coords[index + 1].y)
    //       : null;
    //   if (x && y) {
    //     page.drawImage(img, {
    //       x,
    //       y,
    //       width: scaled.width,
    //       height: scaled.height,
    //     });
    //     const link = this.createPageLinkAnnotation(page, url, {
    //       imgXPos: x,
    //       imgYPos: y,
    //       imgWidth: scaled.width,
    //       imagHeight: scaled.height,
    //     });
    //     page.node.set(PDFName.of("Annots"), pdfDoc.context.obj([link]));
    //   }
    // }
    // const pdfBytes = await pdfDoc.save();
    //lib-pdf end
    //HUMMUS lib start
    // const result = new PDFWStreamForBuffer();
    // const pdfWriter = createWriterToModify(
    //   new PDFRStreamForBuffer(Buffer.from(this.document)),
    //   result
    // );
    // const imageOptions = {
    //   transformation: [0.5, 0, 0, 0.5, 0, 0],
    //   index: 1000,
    // };
    // const pageModifier = new PDFPageModifier(pdfWriter, 0);
    // pageModifier
    //   .startContext()
    //   .getContext()
    //   .drawImage(0, 100, __dirname + "/qrcode.png", imageOptions);
    // pageModifier.endContext().writePage();
    // pdfWriter.end();
    //HUMMUS lib end
    //qrcode as a signature nopodofo pdf lib start
    // const pdfDoc = await pdf(this.document);
    // const field = getSignatureField(pdfDoc);
    // const signer = new npdf.Signer(pdfDoc);
    // signer.signatureField = field;
    // const result = await sign(signer);
    //qrcode as a signature nopodofo pdf lib end
    // return result;
    // return pdfBytes;
    // return result;

    //node signer

    //node signer
  };

  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),
        },
      })
    );

  // imageAppearanceStream(image, rotation, width, height) {
  //   const dict = image.doc.context.obj({
  //     Type: "XObject",
  //     Subtype: "Form",
  //     FormType: 1,
  //     BBox: [0, 0, width, height],
  //     Resources: { XObject: { Image: image.ref } },
  //   });
  //   const operators = [
  //     rotateDegrees(rotation),
  //     translate(0, rotation % 90 === 0 ? -width : 0),
  //     ...drawImage("Image", {
  //       x: 0,
  //       y: width, //y = 0 is width for me
  //       width: width,
  //       height: height,
  //       rotate: degrees(0),
  //       xSkew: degrees(0),
  //       ySkew: degrees(0),
  //     }),
  //   ];
  //   const stream = PDFContentStream.of(dict, operators, false);
  //   return image.doc.context.register(stream);
  // }
}

export default PDFparser;