/**
 * @licstart The following is the entire license notice for the
 * JavaScript code in this page
 *
 * Copyright 2022 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @licend The above is the entire license notice for the
 * JavaScript code in this page
 */
"use strict";

var _test_utils = require("./test_utils.js");

var _primitives = require("../../core/primitives.js");

var _document = require("../../core/document.js");

var _stream = require("../../core/stream.js");

describe("document", function () {
  describe("Page", function () {
    it("should create correct objId/fontId using the idFactory", function () {
      const idFactory1 = (0, _test_utils.createIdFactory)(0);
      const idFactory2 = (0, _test_utils.createIdFactory)(1);
      expect(idFactory1.createObjId()).toEqual("p0_1");
      expect(idFactory1.createObjId()).toEqual("p0_2");
      expect(idFactory1.createFontId()).toEqual("f1");
      expect(idFactory1.createFontId()).toEqual("f2");
      expect(idFactory1.getDocId()).toEqual("g_d0");
      expect(idFactory2.createObjId()).toEqual("p1_1");
      expect(idFactory2.createObjId()).toEqual("p1_2");
      expect(idFactory2.createFontId()).toEqual("f1");
      expect(idFactory2.createFontId()).toEqual("f2");
      expect(idFactory2.getDocId()).toEqual("g_d0");
      expect(idFactory1.createObjId()).toEqual("p0_3");
      expect(idFactory1.createObjId()).toEqual("p0_4");
      expect(idFactory1.createFontId()).toEqual("f3");
      expect(idFactory1.createFontId()).toEqual("f4");
      expect(idFactory1.getDocId()).toEqual("g_d0");
    });
  });
  describe("PDFDocument", function () {
    const stream = new _stream.StringStream("Dummy_PDF_data");

    function getDocument(acroForm, xref = new _test_utils.XRefMock()) {
      const catalog = {
        acroForm
      };
      const pdfManager = {
        get docId() {
          return "d0";
        },

        ensureDoc(prop, args) {
          return pdfManager.ensure(pdfDocument, prop, args);
        },

        ensureCatalog(prop, args) {
          return pdfManager.ensure(catalog, prop, args);
        },

        async ensure(obj, prop, args) {
          const value = obj[prop];

          if (typeof value === "function") {
            return value.apply(obj, args);
          }

          return value;
        }

      };
      const pdfDocument = new _document.PDFDocument(pdfManager, stream);
      pdfDocument.xref = xref;
      pdfDocument.catalog = catalog;
      return pdfDocument;
    }

    it("should get form info when no form data is present", function () {
      const pdfDocument = getDocument(null);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: false,
        hasSignatures: false,
        hasXfa: false,
        hasFields: false
      });
    });
    it("should get form info when XFA is present", function () {
      const acroForm = new _primitives.Dict();
      acroForm.set("XFA", []);
      let pdfDocument = getDocument(acroForm);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: false,
        hasSignatures: false,
        hasXfa: false,
        hasFields: false
      });
      acroForm.set("XFA", ["foo", "bar"]);
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: false,
        hasSignatures: false,
        hasXfa: true,
        hasFields: false
      });
      acroForm.set("XFA", new _stream.StringStream(""));
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: false,
        hasSignatures: false,
        hasXfa: false,
        hasFields: false
      });
      acroForm.set("XFA", new _stream.StringStream("non-empty"));
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: false,
        hasSignatures: false,
        hasXfa: true,
        hasFields: false
      });
    });
    it("should get form info when AcroForm is present", function () {
      const acroForm = new _primitives.Dict();
      acroForm.set("Fields", []);
      let pdfDocument = getDocument(acroForm);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: false,
        hasSignatures: false,
        hasXfa: false,
        hasFields: false
      });
      acroForm.set("Fields", ["foo", "bar"]);
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: true,
        hasSignatures: false,
        hasXfa: false,
        hasFields: true
      });
      acroForm.set("Fields", ["foo", "bar"]);
      acroForm.set("SigFlags", 2);
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: true,
        hasSignatures: false,
        hasXfa: false,
        hasFields: true
      });
      const annotationDict = new _primitives.Dict();
      annotationDict.set("FT", _primitives.Name.get("Sig"));
      annotationDict.set("Rect", [0, 0, 0, 0]);

      const annotationRef = _primitives.Ref.get(11, 0);

      const kidsDict = new _primitives.Dict();
      kidsDict.set("Kids", [annotationRef]);

      const kidsRef = _primitives.Ref.get(10, 0);

      const xref = new _test_utils.XRefMock([{
        ref: annotationRef,
        data: annotationDict
      }, {
        ref: kidsRef,
        data: kidsDict
      }]);
      acroForm.set("Fields", [kidsRef]);
      acroForm.set("SigFlags", 3);
      pdfDocument = getDocument(acroForm, xref);
      expect(pdfDocument.formInfo).toEqual({
        hasAcroForm: false,
        hasSignatures: true,
        hasXfa: false,
        hasFields: true
      });
    });
    it("should get calculation order array or null", function () {
      const acroForm = new _primitives.Dict();
      let pdfDocument = getDocument(acroForm);
      expect(pdfDocument.calculationOrderIds).toEqual(null);
      acroForm.set("CO", [_primitives.Ref.get(1, 0), _primitives.Ref.get(2, 0), _primitives.Ref.get(3, 0)]);
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.calculationOrderIds).toEqual(["1R", "2R", "3R"]);
      acroForm.set("CO", []);
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.calculationOrderIds).toEqual(null);
      acroForm.set("CO", ["1", "2"]);
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.calculationOrderIds).toEqual(null);
      acroForm.set("CO", ["1", _primitives.Ref.get(1, 0), "2"]);
      pdfDocument = getDocument(acroForm);
      expect(pdfDocument.calculationOrderIds).toEqual(["1R"]);
    });
    it("should get field objects array or null", async function () {
      const acroForm = new _primitives.Dict();
      let pdfDocument = getDocument(acroForm);
      let fields = await pdfDocument.fieldObjects;
      expect(fields).toEqual(null);
      acroForm.set("Fields", []);
      pdfDocument = getDocument(acroForm);
      fields = await pdfDocument.fieldObjects;
      expect(fields).toEqual(null);

      const kid1Ref = _primitives.Ref.get(314, 0);

      const kid11Ref = _primitives.Ref.get(159, 0);

      const kid2Ref = _primitives.Ref.get(265, 0);

      const kid2BisRef = _primitives.Ref.get(266, 0);

      const parentRef = _primitives.Ref.get(358, 0);

      const allFields = Object.create(null);

      for (const name of ["parent", "kid1", "kid2", "kid11"]) {
        const buttonWidgetDict = new _primitives.Dict();
        buttonWidgetDict.set("Type", _primitives.Name.get("Annot"));
        buttonWidgetDict.set("Subtype", _primitives.Name.get("Widget"));
        buttonWidgetDict.set("FT", _primitives.Name.get("Btn"));
        buttonWidgetDict.set("T", name);
        allFields[name] = buttonWidgetDict;
      }

      allFields.kid1.set("Kids", [kid11Ref]);
      allFields.parent.set("Kids", [kid1Ref, kid2Ref, kid2BisRef]);
      const xref = new _test_utils.XRefMock([{
        ref: parentRef,
        data: allFields.parent
      }, {
        ref: kid1Ref,
        data: allFields.kid1
      }, {
        ref: kid11Ref,
        data: allFields.kid11
      }, {
        ref: kid2Ref,
        data: allFields.kid2
      }, {
        ref: kid2BisRef,
        data: allFields.kid2
      }]);
      acroForm.set("Fields", [parentRef]);
      pdfDocument = getDocument(acroForm, xref);
      fields = await pdfDocument.fieldObjects;

      for (const [name, objs] of Object.entries(fields)) {
        fields[name] = objs.map(obj => obj.id);
      }

      expect(fields["parent.kid1"]).toEqual(["314R"]);
      expect(fields["parent.kid1.kid11"]).toEqual(["159R"]);
      expect(fields["parent.kid2"]).toEqual(["265R", "266R"]);
      expect(fields.parent).toEqual(["358R"]);
    });
    it("should check if fields have any actions", async function () {
      const acroForm = new _primitives.Dict();
      let pdfDocument = getDocument(acroForm);
      let hasJSActions = await pdfDocument.hasJSActions;
      expect(hasJSActions).toEqual(false);
      acroForm.set("Fields", []);
      pdfDocument = getDocument(acroForm);
      hasJSActions = await pdfDocument.hasJSActions;
      expect(hasJSActions).toEqual(false);

      const kid1Ref = _primitives.Ref.get(314, 0);

      const kid11Ref = _primitives.Ref.get(159, 0);

      const kid2Ref = _primitives.Ref.get(265, 0);

      const parentRef = _primitives.Ref.get(358, 0);

      const allFields = Object.create(null);

      for (const name of ["parent", "kid1", "kid2", "kid11"]) {
        const buttonWidgetDict = new _primitives.Dict();
        buttonWidgetDict.set("Type", _primitives.Name.get("Annot"));
        buttonWidgetDict.set("Subtype", _primitives.Name.get("Widget"));
        buttonWidgetDict.set("FT", _primitives.Name.get("Btn"));
        buttonWidgetDict.set("T", name);
        allFields[name] = buttonWidgetDict;
      }

      allFields.kid1.set("Kids", [kid11Ref]);
      allFields.parent.set("Kids", [kid1Ref, kid2Ref]);
      const xref = new _test_utils.XRefMock([{
        ref: parentRef,
        data: allFields.parent
      }, {
        ref: kid1Ref,
        data: allFields.kid1
      }, {
        ref: kid11Ref,
        data: allFields.kid11
      }, {
        ref: kid2Ref,
        data: allFields.kid2
      }]);
      acroForm.set("Fields", [parentRef]);
      pdfDocument = getDocument(acroForm, xref);
      hasJSActions = await pdfDocument.hasJSActions;
      expect(hasJSActions).toEqual(false);

      const JS = _primitives.Name.get("JavaScript");

      const additionalActionsDict = new _primitives.Dict();
      const eDict = new _primitives.Dict();
      eDict.set("JS", "hello()");
      eDict.set("S", JS);
      additionalActionsDict.set("E", eDict);
      allFields.kid2.set("AA", additionalActionsDict);
      pdfDocument = getDocument(acroForm, xref);
      hasJSActions = await pdfDocument.hasJSActions;
      expect(hasJSActions).toEqual(true);
    });
  });
});