/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { jsPDF as k } from "jspdf";
import { g as G } from "./runtime.js";
import { a as W } from "./queryUtils.js";
import { Sanitizer as $ } from "@esri/arcgis-html-sanitizer";
import * as I from "@esri/solution-common";
import * as S from "@arcgis/core/arcade.js";
import * as j from "@arcgis/core/intl.js";
function H(s, t) {
  const e = document.createElement("a");
  e.download !== void 0 && (e.href = URL.createObjectURL(new Blob([decodeURIComponent("%ef%bb%bf"), t.join("")], { type: "text/csv;charset=utf-8;" })), e.download = `${s}.csv` || "export.csv", e.style.visibility = "hidden", document.body.appendChild(e), e.click(), document.body.removeChild(e));
}
function B(s, t) {
  const e = t.map(
    (i) => Object.values(i).map((o) => `"${o}"`).join(",") + `\r
`
  );
  H(s, e);
}
var y;
(function(s) {
  s.A4 = "A4", s.ANSI_A = "ANSI A";
})(y || (y = {}));
class D {
  // Properties are public for testing purposes
  dataPath = "";
  lang = "en";
  title = "";
  fontProps = {
    fontResolutionInchesPerPoint: 1 / 72,
    fontFullHeightRatio: 1.28
  };
  imageOptions = {
    x: 0,
    y: 0,
    width: 0,
    height: 0
    // inches
  };
  lineOptions = {
    x1: 0,
    y1: 0,
    x2: 0,
    y2: 0,
    lineProperties: {
      thickness: 0.1,
      color: "000000",
      opacity: 1
      // 0..1
    }
  };
  pageOptions = {
    pageType: y.ANSI_A,
    width: 8.5,
    height: 11,
    leftMargin: 0.25,
    rightMargin: 0.25,
    topMargin: 0.25,
    bottomMargin: 0.25,
    drawNeatline: !1
  };
  rectangleOptions = {
    left: 0,
    top: 0,
    width: 8.5,
    height: 11,
    lineProperties: {
      thickness: 0.1,
      color: "000000",
      opacity: 1
      // 0..1
    },
    fillColor: "",
    fillOpacity: 1
    // 0..1
  };
  tableOptions = {
    lineProperties: {
      thickness: 0.1,
      color: "",
      opacity: 1
      // 0..1
    },
    textProperties: {
      left: 0,
      top: 0,
      fontPoints: 1,
      fontColor: "000000"
      // i.e., black
    }
  };
  textOptions = {
    left: 0,
    top: 0,
    fontPoints: 1,
    fontColor: "000000"
    // i.e., black
  };
  //-- Static methods ------------------------------------------------------------------------------------------------//
  /**
   * @class PDFCreator
   */
  static getPageSize(t) {
    switch (typeof t == "string" && (t = t === y.A4 ? y.A4 : y.ANSI_A), t) {
      case y.A4:
        return {
          width: 8.25,
          height: 11.708333
        };
      case y.ANSI_A:
        return {
          width: 8.5,
          height: 11
        };
    }
  }
  //-- Public methods ------------------------------------------------------------------------------------------------//
  /**
   * Adds a page to the document being created.
   *
   * @class PDFCreator
   */
  addPage() {
  }
  /**
   * Calculates a color intensity that emulates an opacity being applied to it.
   *
   * @param colorIntensity Color value to start with; range 0..1
   * @param opacity Opacity to apply; range 0..1
   *
   * @return Color intensity emulating the application of opacity. It works by applying the opacity value
   * to the input colorIntensity and adding the inverse of the opacity. E.g., if opacity is 1, the original
   * colorIntensity is returned; if opacity is 0, 1 is returned; if opacity is 0.5; colorIntensity/2 + 0.5 is
   * returned. It's odd, but when applied to an RGB value, it produces the desired effect.
   *
   * @class PDFCreator
   */
  applyOpacity(t, e) {
    return t * e + 1 * (1 - e);
  }
  /**
   * Draws a PNG image into the page.
   *
   * @params imageDataUrl Image to add to page
   * @params options Position information
   *
   * @class PDFCreator
   */
  drawImage(t, e) {
  }
  /**
   * @class PDFCreator
   */
  drawLine(t) {
    const e = {
      ...this.lineOptions,
      ...t
    };
    e.lineProperties = {
      ...this.lineOptions.lineProperties,
      ...t.lineProperties
    }, this.updateLineProperties(e.lineProperties), this.lineOptions = e;
  }
  /**
   * @class PDFCreator
   */
  drawNeatline(t = {
    thickness: 5e-3,
    color: "0000ff",
    opacity: 0.2
  }) {
    this.drawRectangle({
      left: 0,
      top: 0,
      width: this.pageOptions.width - this.pageOptions.leftMargin - this.pageOptions.rightMargin,
      height: this.pageOptions.height - this.pageOptions.topMargin - this.pageOptions.bottomMargin,
      lineProperties: t
    });
  }
  /**
   * @class PDFCreator
   */
  drawRectangle(t) {
    const e = {
      ...this.rectangleOptions,
      ...t
    };
    e.lineProperties = {
      ...this.lineOptions.lineProperties,
      ...t.lineProperties
    }, this.updateLineProperties(e.lineProperties), (this.rectangleOptions.fillColor !== e.fillColor || this.rectangleOptions.fillOpacity !== e.fillOpacity) && this.setFillColor(e.fillColor, e.fillOpacity), this.rectangleOptions = e;
  }
  /**
   * @class PDFCreator
   */
  drawTable(t, e) {
    const i = {};
    i.lineProperties = {
      ...this.tableOptions.lineProperties,
      ...e.lineProperties
    }, i.textProperties = {
      ...this.tableOptions.textProperties,
      ...e.textProperties
    }, this.tableOptions.textProperties.fontPoints !== i.textProperties.fontPoints && this.setFontSize(i.textProperties.fontPoints), this.tableOptions.textProperties.fontColor !== i.textProperties.fontColor && this.setFontColor(i.textProperties.fontColor), this.updateLineProperties(i.lineProperties), this.tableOptions = i;
  }
  /**
   * @class PDFCreator
   */
  drawText(t, e) {
    const i = {
      ...this.textOptions,
      ...e
    };
    this.textOptions.fontPoints !== i.fontPoints && this.setFontSize(i.fontPoints), this.textOptions.fontColor !== i.fontColor && this.setFontColor(i.fontColor), this.textOptions = i;
  }
  /**
   * Calculates document units from top of font ascenders to baseline.
   *
   * @class PDFCreator
   */
  fontAscenderBaselineHeight(t) {
    return t * this.fontProps.fontResolutionInchesPerPoint;
  }
  /**
   * Calculates document units from top of font ascenders to bottom of descenders.
   *
   * @class PDFCreator
   */
  fontAscenderDescenderHeight(t) {
    return this.fontProps.fontFullHeightRatio * this.fontAscenderBaselineHeight(t);
  }
  /**
   * Returns the name of the font file supporting the specified locale.
   *
   * @param lang Locale such as "en" or "zh-tw"
   * @returns Font name, e.g., "0b7681dc140844ee9f409bdac249fbf0-japanese"
   *
   * @class PDFCreator
   */
  getFontFileName(t) {
    let e = "0b7681dc140844ee9f409bdac249fbf0-general";
    return t === "ja" ? e = "0b7681dc140844ee9f409bdac249fbf0-japanese" : t === "ko" ? e = "0b7681dc140844ee9f409bdac249fbf0-korean" : t === "zh-cn" ? e = "0b7681dc140844ee9f409bdac249fbf0-simplified-chinese" : (t === "zh-hk" || t === "zh-tw") && (e = "0b7681dc140844ee9f409bdac249fbf0-traditional-chinese"), e;
  }
  /**
   * Estimates with width of a string.
   *
   * @param text String to estimate
   * @param fontSize Text size in points
   * @returns Estimated width of text using (points x 1/72 inches/point) * 0.6;
   * need to override this generalized function with a specific PDF generator;
   * the 0.6 width:height ratio comes from https://www.fhwa.dot.gov/publications/research/safety/98057/ch03.cfm#width
   *
   * @class PDFCreator
   */
  getTextWidth(t, e) {
    return t.length * e * this.fontProps.fontResolutionInchesPerPoint * 0.6;
  }
  /**
   * @class PDFCreator
   */
  hexToRGB(t, e = 1) {
    const i = /^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);
    return i ? {
      r: this.applyOpacity(parseInt(i[1], 16) / 255, e),
      g: this.applyOpacity(parseInt(i[2], 16) / 255, e),
      b: this.applyOpacity(parseInt(i[3], 16) / 255, e)
    } : {
      r: 0,
      g: 0,
      b: 0
    };
  }
  /**
   * @class PDFCreator
   */
  async initialize(t = {}, e = "", i = "en", o = "", n = !1) {
    if (JSON.stringify(t) !== "{}") {
      this.pageOptions.pageType = t.pageType === y.A4 ? y.A4 : y.ANSI_A;
      const r = D.getPageSize(this.pageOptions.pageType);
      this.pageOptions.width = r.width, this.pageOptions.height = r.height, this.pageOptions.leftMargin = t.leftMargin ?? this.pageOptions.leftMargin, this.pageOptions.rightMargin = t.rightMargin ?? this.pageOptions.rightMargin, this.pageOptions.topMargin = t.topMargin ?? this.pageOptions.topMargin, this.pageOptions.bottomMargin = t.bottomMargin ?? this.pageOptions.bottomMargin;
    }
    return this.dataPath = e, this.lang = i, this.title = o || "PDF Document", this.pageOptions.drawNeatline = n, Promise.resolve();
  }
  /**
   * @class PDFCreator
   */
  save() {
  }
  /**
   * @class PDFCreator
   */
  setDrawColor(t, e = 1) {
  }
  /**
   * @class PDFCreator
   */
  setFillColor(t, e = 1) {
  }
  /**
   * @class PDFCreator
   */
  setFont(t) {
    return Promise.resolve();
  }
  /**
   * @class PDFCreator
   */
  setFontColor(t) {
  }
  /**
   * @class PDFCreator
   */
  setFontSize(t) {
  }
  /**
   * @class PDFCreator
   */
  setLang(t) {
    return this.lang !== t ? (this.lang = t, this.setFont(t)) : Promise.resolve();
  }
  /**
   * @class PDFCreator
   */
  setLineWidth(t) {
  }
  updateLineProperties(t) {
    this.lineOptions.lineProperties.thickness !== t.thickness && this.setLineWidth(t.thickness), (this.lineOptions.lineProperties.color !== t.color || this.lineOptions.lineProperties.opacity !== t.opacity) && this.setDrawColor(t.color, t.opacity), this.lineOptions.lineProperties = t;
  }
}
class J extends D {
  jsDoc;
  constructor(t = null) {
    super(), this.jsDoc = t;
  }
  //-- Public methods ------------------------------------------------------------------------------------------------//
  /**
   * Adds a page to the document being created.
   *
   * @class PDFCreator_jsPDF
   */
  addPage() {
    super.addPage(), this.jsDoc.addPage(), this.pageOptions.drawNeatline && this.drawNeatline();
  }
  /**
   * Converts a locale into a jsPDF language code.
   *
   * @param lang Locale such as "en" or "en-gb"
   * @returns jsPDF_lang_code jsPDF language code such as "en" or "en-GB", mapping AGO locales "it-it" & "pt-pt"
   * into "it" & "pt", respectively, to match jsPDF offering
   *
   * @class PDFCreator_jsPDF
   */
  convertLocaleToJsPDFLanguageCode(t) {
    let e;
    if (t === "it-it")
      e = "it";
    else if (t === "pt-pt")
      e = "pt";
    else {
      const i = t.split("-");
      i.length === 1 ? e = t : e = i[0] + "-" + i[1].toUpperCase();
    }
    return e;
  }
  /**
   * Draws a PNG image into the page.
   *
   * @params imageDataUrl Image to add to page
   * @params options Position information
   *
   * @class PDFCreator
   */
  drawImage(t, e) {
    this.jsDoc.addImage(t, "PNG", e.x, e.y, e.width, e.height, "", "NONE", 0);
  }
  /**
   * @class PDFCreator_jsPDF
   */
  drawLine(t) {
    super.drawLine(t), this.jsDoc.line(
      this.pageOptions.leftMargin + this.lineOptions.x1,
      this.pageOptions.topMargin + this.lineOptions.y1,
      this.pageOptions.leftMargin + this.lineOptions.x2,
      this.pageOptions.topMargin + this.lineOptions.y2,
      this.lineOptions.lineProperties.color ? "S" : ""
      // line vs. nothing
    );
  }
  /**
   * @class PDFCreator_jsPDF
   */
  drawRectangle(t) {
    super.drawRectangle(t), this.jsDoc.rect(
      this.pageOptions.leftMargin + this.rectangleOptions.left,
      this.pageOptions.topMargin + this.rectangleOptions.top,
      this.rectangleOptions.width,
      this.rectangleOptions.height,
      this.rectangleOptions.lineProperties.color ? this.rectangleOptions.fillColor ? "FD" : "S" : this.rectangleOptions.fillColor ? "F" : ""
      // fill only vs. nothing
    );
  }
  /**
   * @class PDFCreator_jsPDF
   */
  drawTable(t, e) {
    super.drawTable(t, e);
    const i = this.pageOptions.leftMargin + this.textOptions.left, o = this.pageOptions.topMargin + this.textOptions.top;
    this.jsDoc.text(t[0][0], i, o);
  }
  /**
   * @class PDFCreator_jsPDF
   */
  drawText(t, e) {
    super.drawText(t, e);
    let i = this.pageOptions.leftMargin + this.textOptions.left;
    if (this.lang === "ar" || this.lang === "he") {
      const n = this.jsDoc.context2d.measureText(t).width * this.fontProps.fontResolutionInchesPerPoint;
      i = this.pageOptions.width - this.pageOptions.leftMargin - n - this.textOptions.left;
    }
    const o = this.pageOptions.topMargin + this.textOptions.top + this.fontAscenderBaselineHeight(this.textOptions.fontPoints);
    this.jsDoc.text(t, i, o);
  }
  /**
   * Estimates with width of a string.
   *
   * @param {string} text String to estimate
   * @param fontSize Text size in points
   * @returns {number} Estimated width of text in doc units
   *
   * @class PDFCreator_jsPDF
   */
  getTextWidth(t, e) {
    return this.jsDoc.getStringUnitWidth(t) * e / this.jsDoc.internal.scaleFactor;
  }
  /**
   * @class PDFCreator_jsPDF
   */
  async initialize(t = {}, e = "", i = "en", o = "", n = !1) {
    await super.initialize(t, e, i, o, n), this.jsDoc || (this.jsDoc = new k({
      format: t.pageType === y.A4 ? "a4" : "letter",
      orientation: "portrait",
      putOnlyUsedFonts: !0,
      unit: "in"
    })), this.jsDoc.setDocumentProperties({
      title: this.title,
      keywords: "Created with ArcGIS Online"
    }), this.pageOptions.drawNeatline && this.drawNeatline(), await this.setFont(i);
  }
  /**
   * @class PDFCreator_jsPDF
   */
  save() {
    this.jsDoc.save(this.title + ".pdf");
  }
  /**
   * @class PDFCreator_jsPDF
   */
  setDrawColor(t, e = 1) {
    const i = this.hexToRGB(t, e);
    this.jsDoc.setDrawColor(i.r.toString(), i.g.toString(), i.b.toString());
  }
  /**
   * @class PDFCreator_jsPDF
   */
  setFillColor(t, e = 1) {
    const i = this.hexToRGB(t, e);
    this.jsDoc.setFillColor(i.r.toString(), i.g.toString(), i.b.toString());
  }
  /**
   * @class PDFCreator_jsPDF
   */
  setFont(t) {
    this.jsDoc.setLanguage(this.convertLocaleToJsPDFLanguageCode(t));
    const e = this.getFontFileName(t);
    return this.jsDoc.existsFileInVFS(e + ".ttf") ? (this.jsDoc.setFont(e, "normal", "normal"), Promise.resolve()) : fetch(this.dataPath + e + ".txt").then((i) => i.text()).then((i) => (this.jsDoc.addFileToVFS(e + ".ttf", i), this.jsDoc.addFont(e + ".ttf", e, "normal", "normal"), this.jsDoc.setFont(e, "normal", "normal"), Promise.resolve()));
  }
  /**
   * @class PDFCreator_jsPDF
   */
  setFontColor(t) {
    const e = this.hexToRGB(t);
    this.jsDoc.setTextColor(e.r.toString(), e.g.toString(), e.b.toString());
  }
  /**
   * @class PDFCreator_jsPDF
   */
  setFontSize(t) {
    this.jsDoc.setFontSize(t);
  }
  /**
   * @class PDFCreator_jsPDF
   */
  setLineWidth(t) {
    this.jsDoc.setLineWidth(t);
  }
}
function V(s, t = {
  numAcross: 1,
  numDown: 1,
  x0: 0,
  y0: 0,
  width: 1,
  height: 1,
  horizGap: 0,
  vertGap: 0,
  lineProperties: {
    thickness: 0,
    color: "",
    opacity: 1
    // 0..1
  }
}) {
  for (let e = 0; e < t.numDown; ++e)
    for (let i = 0; i < t.numAcross; ++i)
      s.drawRectangle({
        left: t.x0 + i * (t.width + t.horizGap),
        top: t.y0 + e * (t.height + t.vertGap),
        width: t.width,
        height: t.height,
        lineProperties: t.lineProperties
      });
}
class U {
  // Properties are public for testing purposes
  PDFCreator;
  labelFormats;
  //-- Public methods ------------------------------------------------------------------------------------------------//
  /**
   * Add labels to a PDF doc, starting at the beginning of the specified PDF doc page.
   *
   * @param labels Array of labels; each label consists of one or more line strings
   * @param labelSpec Properties describing page dimensions of labels sheet
   * @param startingPageNum The 1-based page number to start printing labels into; page is assumed to be blank & to exist
   * @param heading Line to add at top of label page outside of labels
   * @param progressCallback Callback with percent done in range 0..100
   * @returns Promise which, when resolved, returns the 1-based page number of the last page containing labels
   *
   * @class PDFLabels
   */
  addLabelsToDoc(t, e, i, o, n) {
    return new Promise((r) => {
      const g = e.numLabelsAcross * e.numLabelsDown;
      let l, a, c, p;
      const f = e.labelWidth - 2 * e.labelPadding;
      let w = i;
      const b = e.pageProperties.topMargin - this.PDFCreator.pageOptions.topMargin;
      o && this.drawSupplementalText(o, 0, -0.1);
      for (let O = 0, d = 0; O < t.length; O++) {
        n && n(Math.round(O / t.length * 100));
        let h = t[O].map((F) => F.trim()).filter((F) => F.length > 0);
        if (h.length === 0)
          continue;
        d % g === 0 ? (d > 0 && (this.PDFCreator.addPage(), ++w, o && this.drawSupplementalText(o, 0, -0.1)), l = 0, c = 0, a = 0) : d % e.numLabelsDown === 0 && (c = ++l * (e.labelWidth + e.horizGapIn), a = 0);
        const P = 4;
        let u = e.fontSizePx;
        e.maxNumLabelLines < h.length && (u = Math.max(Math.floor(e.maxNumLabelLines / h.length * e.fontSizePx), P)), u = this._getFontSizeForOverlongLines(h, f, u, P), h = this._clipOverlongLines(h, f, u);
        const m = this.PDFCreator.fontAscenderDescenderHeight(u);
        p = b + a++ * (e.labelHeight + e.vertGapIn), h.forEach((F) => {
          this.PDFCreator.drawText(F, {
            left: c + e.labelPadding,
            top: p + e.labelPadding,
            fontPoints: u,
            fontColor: "000000"
          }), p += m;
        }), ++d;
      }
      n && n(100), r(w);
    });
  }
  drawLabelGuidelines(t, e = null) {
    e !== null && V(this.PDFCreator, {
      // Margins in the page spec are absolute but we draw in within the margins
      x0: t.pageProperties.leftMargin - this.PDFCreator.pageOptions.leftMargin,
      y0: t.pageProperties.topMargin - this.PDFCreator.pageOptions.topMargin,
      numAcross: t.numLabelsAcross,
      numDown: t.numLabelsDown,
      width: t.labelWidth,
      height: t.labelHeight,
      horizGap: t.horizGapIn,
      vertGap: t.vertGapIn,
      lineProperties: e
    });
  }
  /**
   * Draws supplemental text such as a heading or footer.
   *
   * @param text Text to draw
   * @param left Offset from left edge of document to left edge of text
   * @param top Offset from top of document to top of text
   */
  drawSupplementalText(t, e, i) {
    this.PDFCreator.drawText(t, {
      left: e,
      top: i,
      fontPoints: 6,
      fontColor: "000000"
    });
  }
  /**
   * Returns the UI descriptions of the label formats.
   *
   * @returns List of label format descriptions
   *
   * @class PDFLabels
   */
  getAvailableLabelFormats() {
    return this.labelFormats.length > 0 ? this.labelFormats.map((t) => t.descriptionPDF) : [];
  }
  /**
   * Returns the format of the specified label.
   *
   * @param averyPartNumber Avery® label base part number, e.g., "*60" (versus actual part numbers "5160", "8160",
   * "8460", "48160"--all of which are 1" x 2-5/8" rectangular labels)
   * @returns List of label format descriptions
   *
   * @class PDFLabels
   */
  getLabelFormat(t) {
    if (this.labelFormats.length > 0) {
      const e = this.labelFormats.filter((i) => t === i.descriptionPDF.averyPartNumber);
      return e.length > 0 ? e[0] : null;
    } else
      return null;
  }
  /**
   * Loads language font file and label formats into a jsPDF `doc` object.
   *
   * @param PDFCreator PDF-drawing library
   * @throws TypeError "startPDFLabelDoc is stomping on labelFormats property" if the `labelFormats` property
   * is found in doc before the label formats are loaded into the doc.
   *
   * @class PDFLabels
   */
  initialize(t) {
    return this.PDFCreator = t, this._loadLabelFormats(t.dataPath).then((e) => (this.labelFormats = e, Promise.resolve()));
  }
  /**
   * Removes duplicates and empties, trims label lines, and returns a sorted list.
   *
   * @class PDFLabels
   */
  removeDuplicates(t) {
    const i = t.filter((r) => Array.isArray(r) && r.length > 0).map((r) => r.map((g) => g.trim()).join("?")), o = {};
    return i.forEach((r) => o[r] = !0), Object.keys(o).sort().map((r) => r.split("?"));
  }
  //-- Private methods -----------------------------------------------------------------------------------------------//
  /**
   * Calculates the baseline position of the first line of text in a label.
   *
   * @param labelTop Offset from top of document to top of label
   * @param labelHeight Height of each label in doc units
   * @param numLabelLines Number of lines to be drawn in the label
   * @param fontHeight Height of text in doc units
   * @param verticalFontGap Spacing between lines of text in doc units
   * @returns Baseline position
   *
   * @class PDFLabels
   * @private
   */
  _calculateLabelFirstLineBase(t, e, i, o, n) {
    return t + e / 2 + (2 - i) / 2 * o + (1 - i) / 2 * n;
  }
  /**
   * Trims a set of text lines to fit within specified bounds.
   *
   * @param lines Text lines to be trimmed
   * @param maxTextWidth The maximum width permitted for the drawing of the text in doc units
   * @param fontSize Text size in points
   * @returns A copy of lines trimmed as necessary
   *
   * @class PDFLabels
   * @private
   */
  _clipOverlongLines(t, e, i) {
    const o = [];
    return t.forEach((n) => {
      if (n = n.trim(), this.PDFCreator.getTextWidth(n, i) > e) {
        do
          n = n.slice(0, -1);
        while (this.PDFCreator.getTextWidth(n, i) > e);
        n += "...";
      }
      o.push(n);
    }), o;
  }
  /**
   * Trims a set of text lines to fit within specified bounds.
   *
   * @param lines Text lines to be checked
   * @param maxTextWidth The maximum width permitted for the drawing of the text in doc units
   * @param preferredFontSize Initial text size in points
   * @param minimumFontSize The smallest acceptable font size in points
   * @returns The maximum of `minimumFontSize` and the font size in points that should help all lines
   * of the label to fit on the label
   *
   * @class PDFLabels
   * @private
   */
  _getFontSizeForOverlongLines(t, e, i, o) {
    let n = i;
    return t.forEach((r) => {
      if (r = r.trim(), this.PDFCreator.getTextWidth(r, n) > e)
        do
          --n;
        while (this.PDFCreator.getTextWidth(r, n) > e && n > o);
    }), n;
  }
  /**
   * Loads the label formats.
   *
   * @param dataPath Path to the library's data files
   * @returns Promise resolving to the label formats JSON
   *
   * @class PDFLabels
   * @private
   */
  async _loadLabelFormats(t) {
    return await (await fetch(t + "labelFormats.json")).json();
  }
}
function q(s, t, e, i = "", o = "") {
  X(s, t, e, i, o);
}
async function X(s, t, e, i = "", o = "") {
  const n = new J(void 0);
  await n.initialize(
    {
      pageType: "ANSI_A"
    },
    G("assets/arcgis-pdf-creator/"),
    "en",
    s
    // filename without ".pdf"
  );
  const r = new U();
  await r.initialize(n);
  const g = e.labelSpec;
  let l = 1;
  if (o) {
    const a = g.pageProperties, c = D.getPageSize(a.pageType || ""), p = 0.25, f = i ? 0.25 : 0, w = p, b = p + f, O = c.width - 2 * p, d = c.height - 2 * p - f, h = await Y(o);
    let P = w, u = b, m = O, F = d;
    if (h && h.width > 0 && h.height > 0 && O > 0 && d > 0) {
      const L = h.width / h.height, z = O / d;
      L > z ? (m = O, F = O / L, u = b + (d - F) / 2) : (F = d, m = d * L, P = w + (O - m) / 2);
    }
    n.drawImage(o, {
      x: P,
      y: u,
      width: m,
      height: F
    }), i && r.drawSupplementalText(i, 0, -0.1), t.length > 0 && (n.addPage(), ++l);
  }
  await r.addLabelsToDoc(
    t,
    g,
    l,
    i
    // heading
  ), n.save();
}
async function Y(s) {
  return new Promise((t) => {
    const e = new Image();
    e.onload = () => t({ width: e.naturalWidth, height: e.naturalHeight }), e.onerror = () => t(null), e.src = s;
  });
}
const x = "|";
async function M(s, t, e = !0, i = !1, o = !1, n = void 0, r = !1, g = !1) {
  const l = [];
  return Object.keys(t).forEach((c) => {
    const p = t[c], f = p.layerView?.layer || p.layer;
    f && l.push(
      nt(s, f, p.ids, e, i, n, r, g)
    ), o && l.push(Promise.resolve([[c]]));
  }), (await Promise.all(l)).reduce((c, p) => c.concat(p), []);
}
async function dt(s, t, e, i = !1, o = !1, n = void 0, r = !1, g = !1) {
  let l = await M(s, t, e, o, !0, n, r, g);
  l = i ? N(l) : l;
  const a = Object.keys(t);
  let c = [];
  return l.forEach((p) => {
    const f = p[0];
    if (a.indexOf(f) < 0)
      c.push(p);
    else {
      const w = _(t, new RegExp(`\\b${f}\\b`));
      B(E(w), c), c = [];
    }
  }), Promise.resolve();
}
async function gt(s, t, e, i = !1, o = "", n = "") {
  let r = await M(s, t);
  const g = _(t);
  r = // Remove empty lines in labels
  r.map((a) => a.filter((c) => c.length > 0)).filter((a) => a.length > 0), r = i ? N(r) : r;
  const l = o || E(g);
  return q(l, r, e, o, n), Promise.resolve();
}
function N(s) {
  const t = s.map((i) => JSON.stringify(i)), e = new Set(t);
  return Array.from(e, (i) => JSON.parse(i));
}
function A(s) {
  for (s = s.replace(/<br\s*\/?>/gi, x), s = s.replace(/<p[^>]*>/gi, x).trim().replace(/^\|/, ""), s = s.replace(/<\/p>/gi, ""), s = s.replace(/\n/gi, "|"), s = new $().sanitize(s), s = s.replace(/<[\s.]*[^<>]*\/?>/gi, "").replace(/\xA0/gi, " ").replace(/&nbsp;/gi, " "), s = s.replace(/\s*\|\s*/g, "|"); s.match(/\|\|/); )
    s = s.replace(/\|\|/, "|");
  return s = s.replace(/^\|/, ""), s = s.replace(/\|$/, ""), s;
}
function v(s, t = !1) {
  const e = [];
  return s.forEach((i) => {
    (i.visible || t) && e.push(`{${i.fieldName}}`);
  }), {
    type: "pattern",
    format: e.join(x)
  };
}
function K(s) {
  return {
    type: "pattern",
    format: A(s)
  };
}
async function Q(s) {
  const t = {
    variables: [
      {
        name: "$feature",
        type: "feature"
      },
      {
        name: "$layer",
        type: "featureSet"
      },
      {
        name: "$datastore",
        type: "featureSetCollection"
      },
      {
        name: "$map",
        type: "featureSetCollection"
      }
    ]
  }, e = await S.createArcadeExecutor(s.expression, t);
  return Promise.resolve({
    type: "executor",
    format: e
  });
}
async function Z(s, t) {
  const e = {};
  if (!Array.isArray(t?.popupTemplate?.expressionInfos) || t?.popupTemplate?.expressionInfos.length === 0)
    return Promise.resolve(e);
  const i = /\{expression\/\w+\}/g, o = s.match(i);
  if (!o)
    return Promise.resolve(e);
  const n = {
    variables: [
      {
        name: "$feature",
        type: "feature"
      },
      {
        name: "$layer",
        type: "featureSet"
      },
      {
        name: "$datastore",
        type: "featureSetCollection"
      },
      {
        name: "$map",
        type: "featureSetCollection"
      }
    ]
  }, r = {};
  o.forEach((l) => {
    const a = l.substring(l.indexOf("/") + 1, l.length - 1);
    (t?.popupTemplate?.expressionInfos || []).forEach((c) => {
      c.name === a && (r[a] = S.createArcadeExecutor(c.expression, n));
    });
  });
  const g = Object.values(r);
  return Promise.all(g).then((l) => {
    const a = Object.keys(r);
    for (let c = 0; c < a.length; ++c)
      e[a[c]] = l[c].valueOf();
    return e;
  });
}
function E(s) {
  return s.length > 0 ? s.join(", ") : "download";
}
function tt(s) {
  return s.split(x).map((i, o) => {
    const n = i.match(/\{[^\}]*\}/g);
    return n ? n.map((r) => r.substring(1, r.length - 1)).map((r) => r.startsWith("expression/") ? r.substring(r.indexOf("/") + 1) : r).join("__") : `column_${o + 1}`;
  });
}
function et(s) {
  const t = /\{expression\/\w+\}/g;
  return s.match(t) ?? [];
}
function it(s, t, e, i, o) {
  const n = s.substring(s.lastIndexOf("/") + 1);
  Number.isNaN(Number.parseInt(n)) && (s += "/" + t.toString());
  const r = {
    definitionExpression: "1=1",
    httpMethod: "POST",
    objectIds: i,
    outFields: "*",
    relationshipId: e,
    url: s
  };
  return o && (r.params = { token: o }), T(r);
}
function T(s, t = [], e = 0) {
  const i = {
    ...s.params,
    resultOffset: e
  };
  return I.queryRelated({
    ...s,
    params: i
    //TODO } as IQueryRelatedOptionsOffset).then((response: IQueryRelatedResponseOffset) => {
  }).then((o) => (t.push(...o.relatedRecordGroups), o.exceededTransferLimit ? T(s, t, e + o.relatedRecordGroups.length) : Promise.resolve(t)));
}
function st(s) {
  const t = [];
  let e = 0;
  for (; e < s.length; ) {
    const o = s.indexOf("{", e);
    if (o < 0)
      break;
    const n = s.indexOf("}", o);
    if (n < 0)
      break;
    const r = s.substring(o, n + 1);
    t.push(r), e = n + 1;
  }
  const i = et(s);
  return t.filter((o) => i.indexOf(o) < 0);
}
function ot(s) {
  return s.map((t) => t.substring(1, t.length - 1));
}
async function C(s, t, e) {
  let i = {
    layer: t,
    attributeFormats: {},
    relationshipId: void 0,
    labelFormat: {
      type: "unsupported",
      format: void 0
    }
  };
  if (t.popupEnabled && ((t?.popupTemplate?.fieldInfos || []).forEach(
    // Extract any format info that we have
    (o) => {
      o.format && (i.attributeFormats[o.fieldName.toLowerCase()] = o.format);
    }
  ), e && t)) {
    const o = t?.popupTemplate?.content || [], n = o && o.length > 0 ? o[0]?.type : void 0;
    if (n === "relationship") {
      const r = o[0].relationshipId, g = t.relationships?.find((a) => a.id === r);
      let l = s.layers.toArray().concat(s.tables.toArray());
      if (l = l.filter((a) => a.type === "feature" && a.layerId === g?.relatedTableId), l.length > 0)
        i = await C(s, l[0], e), i.relationshipId = r.toString();
      else {
        l = s.layers.toArray().concat(s.tables.toArray());
        const a = [];
        l = l.filter((f) => {
          if (f.type === "feature" && f.layerId != t.layerId && f.url) {
            const w = f.url + "/" + f?.layerId?.toString();
            return a.push(I.getJson(
              w
              /*, authentication*/
            )), !0;
          } else
            return !1;
        });
        const c = await Promise.all(a);
        let p = Promise.resolve(void 0);
        c.some((f, w) => f.relationships && f.relationships.some((b) => b.id === r) ? (p = C(s, l[w], e), !0) : !1) ? (i = await p, i.relationshipId = r.toString()) : i.labelFormat = v(t.popupTemplate?.fieldInfos);
      }
    } else n === "fields" ? (i.labelFormat = v(t.popupTemplate?.fieldInfos), i.labelFormat.format.length === 0 && (i.labelFormat = t.popupTemplate?.title && typeof t.popupTemplate?.title == "string" ? { type: "pattern", format: t.popupTemplate.title } : (
      // Otherwise revert to using attributes
      v(t.popupTemplate?.fieldInfos, !0)
    ))) : n === "text" ? i.labelFormat = K(o[0].text) : n === "expression" ? i.labelFormat = await Q(o[0].expressionInfo) : i.labelFormat = v(t.popupTemplate?.fieldInfos);
  }
  return Promise.resolve(i);
}
function _(s, t = /.+/) {
  let e = [];
  return Object.keys(s).forEach((i) => {
    const o = s[i];
    t.test(i) && (e = e.concat(o.selectionSetNames));
  }), e;
}
function R(s, t, e, i, o) {
  if (s === null || typeof s > "u")
    return "";
  if (e && e.type === "coded-value")
    return e.getName(s)?.toString();
  {
    let n = s;
    switch (t) {
      case "date":
        if (i?.dateFormat) {
          const r = o.convertDateFormatToIntlOptions(i.dateFormat);
          n = o.formatDate(n, r);
        } else
          n = o.formatDate(n);
        n = n.replace(/\xe2\x80\xaf/g, "");
        break;
      case "date-only":
        if (i?.dateFormat) {
          const r = o.convertDateFormatToIntlOptions(i.dateFormat);
          n = o.formatDateOnly(n, r);
        } else
          n = o.formatDateOnly(n);
        break;
      case "time-only":
        if (i?.dateFormat) {
          const r = o.convertDateFormatToIntlOptions(i.dateFormat);
          n = o.formatTimeOnly(n, r);
        } else
          n = o.formatTimeOnly(n);
        break;
      case "double":
      case "integer":
      case "long":
      case "small-integer":
        if (i) {
          const r = o.convertNumberFormatToIntlOptions(i);
          n = o.formatNumber(n, r);
        } else
          n = o.formatNumber(n?.toString(), {
            maximumFractionDigits: 100
          });
        break;
    }
    return n;
  }
}
async function nt(s, t, e, i = !0, o = !1, n = [], r = !1, g = !1) {
  const l = s?.portalItem?.portal?.credential?.token, a = await C(s, t, i), c = a.layer;
  let p = [];
  if (typeof a.relationshipId < "u") {
    const d = await it(t.url, t.layerId, a.relationshipId, e, l), h = [];
    d.forEach((u) => {
      u.relatedRecords?.forEach((m) => {
        h.push(m.attributes);
      });
    });
    const P = t.objectIdField;
    if (h.sort((u, m) => u[P] < m[P] ? -1 : u[P] > m[P] ? 1 : 0), p = h.filter((u, m) => m === 0 ? !0 : u[P] !== h[m - 1][P]), p.length === 0)
      return Promise.resolve([]);
  } else {
    const d = n.length > 0 ? n : void 0;
    p = await W(e, c, [], !1, void 0, d);
  }
  const f = {}, w = {}, b = {};
  c.fields && n ? c.fields.forEach((d) => {
    if (!g || n.indexOf((d?.name || "").toLowerCase()) > -1) {
      const h = d.name.toLowerCase();
      f[h] = d.name, b[h] = d.domain, w[h] = d.type;
    }
  }) : n && Object.keys(p[0]).forEach((d) => {
    if (!g || n.indexOf(d.toLowerCase()) > -1) {
      const h = d.toLowerCase();
      f[h] = d;
    }
  });
  const O = a.labelFormat.type === "pattern" ? (
    // Export attributes in format
    await at(
      t,
      p,
      f,
      w,
      b,
      a.attributeFormats,
      a.labelFormat.format,
      o
    )
  ) : a.labelFormat.type === "executor" ? (
    // Export attributes in expression
    await lt(p, a.labelFormat.format)
  ) : (
    // Export all attributes
    await rt(p, w, b, o, r)
  );
  return Promise.resolve(O);
}
async function rt(s, t, e, i = !1, o = !1) {
  const n = s.map((r) => Object.keys(r.attributes).map((g) => {
    const l = g.toLowerCase();
    return R(r.attributes[g], t[l], e[l], void 0, j);
  }));
  if (i) {
    const r = [], g = s[0].attributes, l = s[0]?.layer?.fields.reduce((a, c) => (a[c.name] = c.alias, a), {});
    Object.keys(g).forEach((a) => {
      r.push(o && l ? l[a] : a);
    }), n.unshift(r);
  }
  return Promise.resolve(n);
}
async function at(s, t, e, i, o, n, r, g = !1) {
  const l = st(r), a = ot(l), c = await Z(r, s), p = /\{expression\/\w+\}/g, f = r.match(p) ?? [], w = await Promise.all(
    t.map(async (b) => {
      let O = r;
      for (let P = 0; P < f.length; P++) {
        const u = f[P], m = u.substring(u.indexOf("/") + 1, u.length - 1), F = await c[m].executeAsync({ $feature: b, $layer: s });
        F && (O = O.replace(u, F).replace(/\n/gi, "|"));
      }
      const d = b.attributes ?? b;
      a.forEach((P, u) => {
        const m = P.toLowerCase(), F = R(
          d[e[m]],
          i[m],
          o[m],
          n[m],
          j
        );
        O = O.replace(l[u], F);
      });
      let h = O.split(x);
      return h = h.map((P) => A(P)), h;
    })
  );
  return g && w.unshift(tt(r)), Promise.resolve(w);
}
async function lt(s, t) {
  const i = (await Promise.all(
    s.map(async (o) => t.executeAsync({ $feature: o }))
  )).filter((o) => o?.text).map((o) => A(o.text).split(x));
  return Promise.resolve(i);
}
export {
  R as _,
  gt as a,
  _ as b,
  M as c,
  dt as d,
  E as e,
  N as r
};
