/* COPYRIGHT Esri - https://js.arcgis.com/5.0/LICENSE.txt */
import { c as k } from "../../chunks/runtime.js";
import { css as L, html as p } from "lit";
import * as _ from "@arcgis/core/geometry/operators/cutOperator.js";
import * as g from "@arcgis/core/geometry/operators/lengthOperator.js";
import * as y from "@arcgis/core/geometry/operators/projectOperator.js";
import v from "@arcgis/core/geometry/Polyline.js";
import S from "@arcgis/core/geometry/SpatialReference.js";
import A from "@arcgis/core/Graphic.js";
import m from "@arcgis/core/rest/networks/support/TraceLocation.js";
import b from "@arcgis/core/symbols/SimpleMarkerSymbol.js";
import { LitElement as x, createEvent as w } from "@arcgis/lumina";
import { log as c } from "@arcgis/toolkit/log";
import { u as I } from "../../chunks/useT9n.js";
const C = L`calcite-block{--calcite-block-content-space: 0;--calcite-block-border-color: transparent;margin:0}.add-location-button{--calcite-button-border-color: var(--calcite-color-border-1);--calcite-button-icon-color: var(--calcite-color-text-1);--calcite-button-text-color: var(--calcite-color-text-1)}.button-container{justify-content:center;display:grid}.clear-button{--calcite-button-border-color: transparent}`;
class F extends x {
  constructor() {
    super(...arguments), this.messages = I({ blocking: !0 }), this.isSelectWaiting = !1, this.traceLocationType = "starting-point", this.spatialTolerance = 0.05, this.autoDestroyDisabled = !1, this.arcgisTraceLocationChange = w(), this.arcgisTraceLocationSelectEnd = w(), this.arcgisTraceLocationSelectStart = w();
  }
  static {
    this.properties = { isSelectWaiting: 16, beforeTraceLocationSelectStart: 0, afterHitTest: 0, view: 0, traceLocationType: 1, traceLocations: 0, filterLayers: 0, sketchViewModel: 0, flagLayer: 0, spatialTolerance: 9, autoDestroyDisabled: 5, utilityNetwork: 0 };
  }
  static {
    this.styles = C;
  }
  async destroy() {
    this._resetAfterSketch(!1), await this.manager.destroy();
  }
  async load() {
    y.isLoaded() || await y.load();
  }
  _createPolyline(e, t) {
    return new v({
      hasZ: !1,
      hasM: !0,
      paths: e,
      spatialReference: new S({ wkid: t })
    });
  }
  _calculatePercentAlong(e, t) {
    const r = e.spatialReference, a = this._createPolyline(e.paths, r.wkid), s = t.x - 0.5, n = t.x + 0.5, o = t.y - 0.5, i = t.y + 0.5, l = [
      [
        [s, o],
        [n, i]
      ]
    ], u = this._createPolyline(l, t.spatialReference.wkid), d = y.execute(u, r);
    if (!d)
      return c("error", this, "Unable to project flag geometry to source geometry spatial reference."), 0.5;
    const h = _.execute(a, d);
    if (h.length > 0) {
      const T = g.execute(a, { unit: "feet" });
      let f;
      return h[0].paths[0][0][0] === a.paths[0][0][0] ? f = g.execute(h[0], { unit: "feet" }) : h.length > 1 ? f = g.execute(h[1], { unit: "feet" }) : f = 0, f / T;
    }
    return c("warn", this, "Unable to cut the source geometry with the flag geometry."), 0.5;
  }
  async _ensureNecessaryAttributes(e) {
    const t = (e.layer?.type === "feature", e.layer), r = t.fieldsIndex?.get("assetgroup") ?? !1, a = t.fieldsIndex?.get("assetgroup")?.name ?? "assetgroup", s = t.fieldsIndex?.get("assettype") ?? !1, n = t.fieldsIndex?.get("assettype")?.name ?? "assettype", o = e.getGlobalId(), i = e.getObjectId(), l = r ? !!e.getAttribute(a) : !0, u = s ? !!e.getAttribute(n) : !0;
    if (o && i && l && u)
      return e;
    const d = t.createQuery();
    return d.objectIds = [i], (await t.queryFeatures(d))?.features[0] || null;
  }
  async _ensureNecessaryAttributesAndGenerateTraceLocation(e, t) {
    const { view: r } = this;
    if (!r || e.length === 0) {
      c("error", this, "`view` is unavailable or there are no results to process.");
      return;
    }
    const a = e[0], s = e.map((i) => {
      const l = i, u = l.graphic;
      return u.origin = l.layer, u;
    }), n = this.afterHitTest ? await this.afterHitTest(s).catch(() => (this._resetAfterSketch(!0), null)) : a.graphic;
    if (!n) {
      c("error", this, "No graphic available from hit test results.");
      return;
    }
    const o = await this._ensureNecessaryAttributes(n);
    if (!o) {
      c("error", this, "Unable to ensure necessary attributes on the selected graphic.");
      return;
    }
    await this._generateTraceLocation(o, t);
  }
  _createFlagSymbol() {
    const { traceLocationType: e } = this, t = [244, 21, 21, 0.6], r = [21, 244, 21, 0.6];
    return e === "stopping-point" ? new b({
      color: t,
      style: "x",
      size: 12,
      outline: {
        color: t,
        width: 2
      }
    }) : e === "barrier" ? new b({
      color: t,
      style: "square",
      size: 12,
      outline: {
        color: t,
        width: 0
      }
    }) : new b({
      color: r,
      style: "circle",
      size: 12,
      outline: {
        color: r,
        width: 0
      }
    });
  }
  _addFlagGraphic(e, t, r) {
    const { flagLayer: a, view: s } = this;
    if (!a || !s)
      return c("error", this, "The properties `flagLayer` and `view` are required but either one or both are missing."), null;
    const n = t.geometry?.type;
    if (this.traceLocations?.some((l) => l.traceLocation.globalId === e) && n !== "polyline")
      return c("warn", this, "A flag with the same globalId already exists."), null;
    const o = this._createFlagSymbol(), i = new A({
      geometry: r,
      symbol: o,
      attributes: t.attributes
    });
    return a.add(i), i;
  }
  async _generateItemTitle(e) {
    const { messages: t } = this, r = (e.layer?.type === "feature", e.layer);
    return ("getFeatureTitle" in r ? await r.getFeatureTitle(e) : null) || e?.getObjectId()?.toString() || t.labels.unknown;
  }
  async _generateFlagInfo(e, t) {
    const { traceLocationType: r, utilityNetwork: a } = this, s = e.getGlobalId() ?? "", n = e.geometry?.type, o = await this._generateItemTitle(e);
    if (n === "point" || n === "polygon") {
      const i = a?.getTerminalConfiguration(e), l = i ? i.terminals[0].id : 1;
      return {
        traceLocation: new m({
          type: r,
          isFilterBarrier: !1,
          globalId: s,
          terminalId: l
        }),
        flagProperties: {
          title: o,
          expanded: !1,
          terminalConfiguration: i ?? void 0,
          selectedTerminals: i ? /* @__PURE__ */ new Set([l]) : void 0
        },
        spatialProperties: {
          mapPoint: t,
          mapGraphic: e
        }
      };
    } else if (n === "polyline") {
      const i = this._calculatePercentAlong(e.geometry, t);
      return {
        traceLocation: new m({
          type: r,
          isFilterBarrier: !1,
          globalId: s,
          percentAlong: i
        }),
        flagProperties: {
          title: o,
          expanded: !1
        },
        spatialProperties: {
          mapPoint: t,
          mapGraphic: e
        }
      };
    } else if (!n) {
      const i = a?.getTerminalConfiguration(e), l = i ? i.terminals[0].id : 1;
      return {
        traceLocation: new m({
          type: r,
          isFilterBarrier: !1,
          globalId: s,
          terminalId: l
        }),
        flagProperties: {
          title: o,
          expanded: !1,
          terminalConfiguration: i ?? void 0,
          selectedTerminals: i ? /* @__PURE__ */ new Set([l]) : void 0
        },
        spatialProperties: {
          mapPoint: t
        }
      };
    }
    return null;
  }
  async _generateTraceLocation(e, t) {
    const { traceLocations: r } = this, a = e.getGlobalId() ?? "", s = e.geometry?.type, n = await this._generateFlagInfo(e, t);
    if (!n) {
      c("error", this, "Unable to generate flag info for trace location.");
      return;
    }
    const o = r?.filter((i) => i.spatialProperties.mapGraphic?.getGlobalId() === a) ?? [];
    if (o.length === 0 || s === "polyline") {
      if (s === "polyline" && o.length > 0 && o.some((l) => Math.abs(l.traceLocation.percentAlong - n.traceLocation.percentAlong) <= this.spatialTolerance)) {
        c("warn", this, "A flag with the same globalId already exists within tolerance.");
        return;
      }
      const i = this._addFlagGraphic(a, e, t);
      if (!i) {
        c("warn", this, "Unable to add flag graphic.");
        return;
      }
      n.spatialProperties.flagGraphic = i, r?.add(n);
      return;
    }
    c("warn", this, "A flag with the same globalId already exists.");
  }
  async _hitTest(e) {
    const { view: t, utilityNetwork: r } = this;
    if (!t || !r)
      return c("error", this, "Either `utilityNetwork` or `view` is unavailable for hit test."), !0;
    const a = e.graphic?.geometry, s = this.view?.toScreen(a);
    if (!s)
      return c("warn", this, "No screen point available for hit test."), !1;
    const o = (await t.hitTest(s, {
      include: this.filterLayers
    })).results.filter((i) => i.type === "graphic" && i?.layer && i.graphic);
    return o.length === 0 ? (c("info", this, "No usable hit test results found."), !1) : (this._resetAfterSketch(!1), await this._ensureNecessaryAttributesAndGenerateTraceLocation(o, a), this._resetAfterSketch(!0), !0);
  }
  _resetAfterSketch(e = !1) {
    const { view: t } = this;
    if (!t) {
      c("error", this, "View is not available to reset after sketch.");
      return;
    }
    this._clickHandler?.remove(), this._clickHandler = void 0, "acquireCursor" in t && t.acquireCursor("default"), e && this.arcgisTraceLocationSelectEnd.emit();
  }
  _handleSketchComplete(e) {
    const { sketchViewModel: t, view: r } = this;
    if (!t || !r) {
      c("error", this, "Either `sketchViewModel` or `view` is not available in sketch complete handler.");
      return;
    }
    if (e.state === "complete" && e.graphic) {
      t.layer.remove(e.graphic), this._hitTest(e).then((s) => {
        s ? this._resetAfterSketch() : this._initiateHitTest();
      });
      return;
    }
    e.state === "cancel" && this._resetAfterSketch(!0);
  }
  async _initiateHitTest() {
    const { view: e, sketchViewModel: t } = this;
    if (!e || !t) {
      c("error", this, "Cannot initiate hit test; either `view` or `sketchViewModel` not found.");
      return;
    }
    this._clickHandler?.remove(), this._clickHandler = t.on("create", this._handleSketchComplete.bind(this)), "acquireCursor" in e && e.acquireCursor("crosshair"), this.sketchViewModel?.create("point");
  }
  async _handleAddButtonClick() {
    const { view: e, sketchViewModel: t } = this;
    if (!(e && t)) {
      c("error", this, "Cannot add trace location; `view` not found.");
      return;
    }
    if (this.beforeTraceLocationSelectStart) {
      this.isSelectWaiting = !0;
      try {
        await this.beforeTraceLocationSelectStart();
      } finally {
        this.isSelectWaiting = !1;
      }
    }
    this.arcgisTraceLocationSelectStart.emit({ cancelSelect: () => t.cancel() }).defaultPrevented || await this._initiateHitTest();
  }
  _handleClearButtonClick() {
    const { flagLayer: e, traceLocations: t } = this;
    t?.forEach((r) => {
      r.spatialProperties.flagGraphic && e && e.remove(r.spatialProperties.flagGraphic);
    }), t?.removeAll();
  }
  renderAddLocationBlock() {
    const { traceLocationType: e, messages: t, traceLocations: r } = this, a = e === "starting-point" ? t.types.startingPoint : e === "barrier" ? t.types.barrier : t.types.stoppingPoint, s = a.heading, n = a.description, o = a.buttonText;
    return p`<calcite-block .heading=${s} .label=${s} expanded .description=${n}>${r?.length ? p`<calcite-button class="clear-button" slot=actions-end appearance=transparent .label=${t.buttons.clear} @click=${() => this._handleClearButtonClick()}>${t.buttons.clear}</calcite-button>` : null}<arcgis-utility-network-trace-location-list .traceLocations=${r} .traceLocationType=${e}></arcgis-utility-network-trace-location-list><div class="button-container"><calcite-button .loading=${this.isSelectWaiting} class="add-location-button" icon-start=select appearance=outline .label=${o} @click=${() => this._handleAddButtonClick()}>${o}</calcite-button></div></calcite-block>`;
  }
  render() {
    return p`<div class="root">${this.renderAddLocationBlock()}</div>`;
  }
}
k("arcgis-utility-network-trace-location", F);
export {
  F as ArcgisUtilityNetworkTraceLocation
};
