/* COPYRIGHT Esri - https://js.arcgis.com/5.2/LICENSE.txt */
import { c as k } from "../../chunks/runtime.js";
import { css as x, html as y } from "lit";
import * as C from "@arcgis/core/geometry/operators/cutOperator.js";
import * as m from "@arcgis/core/geometry/operators/lengthOperator.js";
import * as b from "@arcgis/core/geometry/operators/projectOperator.js";
import I from "@arcgis/core/geometry/Polyline.js";
import G from "@arcgis/core/geometry/SpatialReference.js";
import F from "@arcgis/core/Graphic.js";
import T from "@arcgis/core/rest/networks/support/TraceLocation.js";
import L from "@arcgis/core/symbols/SimpleMarkerSymbol.js";
import { LitElement as v, createEvent as w } from "@arcgis/lumina";
import { log as l, composeMissingPropertyMessage as g } from "@arcgis/toolkit/log";
import { u as A } from "../../chunks/useT9n.js";
import { d as S, i as P } from "../../chunks/layer-utils.js";
const N = x`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 R extends v {
  constructor() {
    super(...arguments), this.messages = A({ 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, spatialTolerance: 9, autoDestroyDisabled: 5, utilityNetwork: 0 };
  }
  static {
    this.styles = N;
  }
  async destroy() {
    this._resetCursor(), await this.manager.destroy();
  }
  async load() {
    b.isLoaded() || await b.load();
  }
  _createPolyline(e, t) {
    return new I({
      hasZ: !1,
      hasM: !0,
      paths: e,
      spatialReference: new G({ wkid: t })
    });
  }
  _calculatePercentAlong(e, t) {
    const r = e.spatialReference, s = this._createPolyline(e.paths, r.wkid), o = t.x - 0.5, a = t.x + 0.5, c = t.y - 0.5, i = t.y + 0.5, u = [
      [
        [o, c],
        [a, i]
      ]
    ], n = this._createPolyline(u, t.spatialReference.wkid), p = b.execute(n, r);
    if (!p)
      return l("error", this, "Unable to project flag geometry to source geometry spatial reference."), -1;
    const d = C.execute(s, p);
    if (d.length > 0) {
      const h = m.execute(s, { unit: "feet" });
      let f;
      return d[0].paths[0][0][0] === s.paths[0][0][0] ? f = m.execute(d[0], { unit: "feet" }) : d.length > 1 ? f = m.execute(d[1], { unit: "feet" }) : f = 0, f / h;
    }
    return l("warn", this, "Unable to cut the source geometry with the flag geometry."), -1;
  }
  get _edgeSourceLayerIds() {
    const e = this.utilityNetwork?.dataElement?.domainNetworks;
    return e ? e.flatMap((t) => t.edgeSources).map((t) => t.layerId).filter(Boolean) : [];
  }
  async _handleAddButtonClick() {
    const { view: e, sketchViewModel: t } = this;
    if (!(e && t)) {
      l("error", this, "Cannot add trace location."), t || l("error", this, g("sketchViewModel")), e || l("error", this, g("view"));
      return;
    }
    if (this.beforeTraceLocationSelectStart) {
      this.isSelectWaiting = !0;
      try {
        await this.beforeTraceLocationSelectStart();
      } finally {
        this.isSelectWaiting = !1;
      }
    }
    await this._startSketch(e, t);
  }
  async _startSketch(e, t) {
    this.arcgisTraceLocationSelectStart.emit({ cancelSelect: () => t.cancel() }).defaultPrevented || (this._clickHandler?.remove(), this._clickHandler = t.on("create", (s) => this._handleSketchComplete(s, e, t)), "acquireCursor" in e && e.acquireCursor("crosshair"), t.snappingOptions.enabled = !0, t.create("point"));
  }
  _handleSketchComplete(e, t, r) {
    if (e.state === "complete" && e.graphic) {
      r.layer.remove(e.graphic), this._performHitTest(e, t, r);
      return;
    }
    e.state === "cancel" && (this._resetCursor(), this.arcgisTraceLocationSelectEnd.emit());
  }
  async _performHitTest(e, t, r) {
    const { utilityNetwork: s } = this;
    if (!s) {
      l("error", this, g("utilityNetwork")), this._resetCursor(), this.arcgisTraceLocationSelectEnd.emit();
      return;
    }
    const o = e.graphic?.geometry, a = t.toScreen(o);
    if (!a) {
      l("warn", this, "No screen point available for hit test."), this._startSketch(t, r);
      return;
    }
    const i = (await t.hitTest(a, {
      include: this.filterLayers
    })).results.filter((n) => n.type === "graphic" && n?.layer && n.graphic);
    if (i.length === 0) {
      l("info", this, "No usable hit test results found."), this._startSketch(t, r);
      return;
    }
    this._resetCursor(), await this._processHitTestResults(i, o, t) ? this.arcgisTraceLocationSelectEnd.emit() : this._startSketch(t, r);
  }
  _resetCursor() {
    const { view: e, sketchViewModel: t } = this;
    if (!e) {
      l("error", this, g("view"));
      return;
    }
    t && (t.snappingOptions.enabled = !1), this._clickHandler?.remove(), this._clickHandler = void 0, "acquireCursor" in e && e.acquireCursor("default");
  }
  async _processHitTestResults(e, t, r) {
    if (e.length === 0)
      return l("error", this, "There are no hit test results to process."), !1;
    const s = e[0], o = e.map((u) => {
      const n = u, p = n.graphic;
      return p.origin = n.layer, p.sourceLayer = n.layer, p;
    });
    let a = s.graphic;
    if (this.afterHitTest)
      try {
        a = await this.afterHitTest(o);
      } catch {
        a = null;
      }
    if (!a)
      return l("error", this, "No graphic available from hit test results."), this.arcgisTraceLocationSelectEnd.emit(), !0;
    const c = await this._ensureNecessaryAttributes(a);
    return c ? await this._generateTraceLocation(c, t, r) : (l("error", this, "Unable to ensure necessary attributes on the selected graphic."), this.arcgisTraceLocationSelectEnd.emit(), !0);
  }
  async _ensureNecessaryAttributes(e) {
    const t = (S(e.layer), e.layer), r = t.geometryType === null, s = t.fieldsIndex?.get("assetgroup") ?? !1, o = t.fieldsIndex?.get("assetgroup")?.name ?? "assetgroup", a = t.fieldsIndex?.get("assettype") ?? !1, c = t.fieldsIndex?.get("assettype")?.name ?? "assettype", i = e.getGlobalId(), u = e.getObjectId(), n = s ? !!e.getAttribute(o) : !0, p = a ? !!e.getAttribute(c) : !0, d = !!e.geometry;
    if (i && u && n && p && (d || r))
      return e;
    const h = t.createQuery();
    return h.objectIds = [u], (await t.queryFeatures(h))?.features[0] || null;
  }
  async _generateTraceLocation(e, t, r) {
    const { traceLocations: s } = this, o = e.getGlobalId() ?? "", a = e.geometry?.type, c = await this._generateFlagInfo(e, t);
    if (!c)
      return l("error", this, "Unable to generate flag info for trace location."), !1;
    const i = s?.filter((n) => n.spatialProperties.mapGraphic?.getGlobalId() === o) ?? [];
    if (i.length > 0) {
      if (a !== "polyline")
        return l("warn", this, "A flag with the same globalId already exists."), !1;
      if (i.some((n) => Math.abs(n.traceLocation.percentAlong - c.traceLocation.percentAlong) <= this.spatialTolerance))
        return l("warn", this, "A flag with the same globalId already exists within tolerance."), !1;
    }
    const u = this._addFlagGraphic(e, t, r);
    return u ? (c.spatialProperties.flagGraphic = u, s?.add(c), !0) : (l("warn", this, "Unable to add flag graphic."), !1);
  }
  async _generateFlagInfo(e, t) {
    const { traceLocationType: r, utilityNetwork: s } = this, o = e.getGlobalId() ?? "", a = e.geometry?.type, c = await this._generateItemTitle(e);
    if (a === "point" || a === "polygon") {
      const i = s?.getTerminalConfiguration(e), u = i ? i.terminals[0].id : 1;
      return {
        traceLocation: new T({
          type: r,
          isFilterBarrier: !1,
          globalId: o,
          terminalId: u
        }),
        flagProperties: {
          title: c,
          expanded: !1,
          terminalConfiguration: i ?? void 0,
          selectedTerminals: i ? /* @__PURE__ */ new Set([u]) : void 0
        },
        spatialProperties: {
          mapPoint: t,
          mapGraphic: e
        }
      };
    } else if (a === "polyline") {
      const i = this._calculatePercentAlong(e.geometry, t);
      return i < 0 ? (l("warn", this, "Unable to calculate percent along for polyline flag."), null) : {
        traceLocation: new T({
          type: r,
          isFilterBarrier: !1,
          globalId: o,
          percentAlong: i
        }),
        flagProperties: {
          title: c,
          expanded: !1,
          terminalConfiguration: void 0,
          selectedTerminals: void 0
        },
        spatialProperties: {
          mapPoint: t,
          mapGraphic: e
        }
      };
    } else if (!a) {
      const i = P(e.layer) ? e.layer.parent : e.layer, u = i && this._edgeSourceLayerIds.includes(i.layerId), n = s?.getTerminalConfiguration(e), p = n ? n.terminals[0].id : u ? -1 : 1, d = u ? 0.5 : -1;
      return {
        traceLocation: new T({
          type: r,
          isFilterBarrier: !1,
          globalId: o,
          terminalId: p,
          percentAlong: d
        }),
        flagProperties: {
          title: c,
          expanded: !1,
          terminalConfiguration: n ?? void 0,
          selectedTerminals: n ? /* @__PURE__ */ new Set([p]) : void 0
        },
        spatialProperties: {
          mapPoint: t,
          mapGraphic: e
        }
      };
    }
    return null;
  }
  async _generateItemTitle(e) {
    const { messages: t } = this, r = (S(e.layer), e.layer);
    return ("getFeatureTitle" in r ? await r.getFeatureTitle(e) : null) || e?.getObjectId()?.toString() || t.labels.unknown;
  }
  _addFlagGraphic(e, t, r) {
    const s = e.geometry ? e.geometry.type === "point" ? e.geometry : t : null, o = this._createFlagSymbol(), a = new F({
      geometry: s,
      symbol: o,
      attributes: e.attributes
    });
    return r.graphics.add(a), a;
  }
  _createFlagSymbol() {
    const { traceLocationType: e } = this, t = [244, 21, 21, 0.6], r = [21, 244, 21, 0.6];
    return e === "stopping-point" ? new L({
      color: t,
      style: "x",
      size: 12,
      outline: {
        color: t,
        width: 2
      }
    }) : e === "barrier" ? new L({
      color: t,
      style: "square",
      size: 12,
      outline: {
        color: t,
        width: 0
      }
    }) : new L({
      color: r,
      style: "circle",
      size: 12,
      outline: {
        color: r,
        width: 0
      }
    });
  }
  _handleClearButtonClick() {
    const { view: e, traceLocations: t } = this;
    t?.forEach((r) => {
      r.spatialProperties.flagGraphic && e && e.graphics.remove(r.spatialProperties.flagGraphic);
    }), t?.removeAll();
  }
  renderAddLocationBlock() {
    const { traceLocationType: e, messages: t, traceLocations: r, view: s } = this, o = e === "starting-point" ? t.types.startingPoint : e === "barrier" ? t.types.barrier : t.types.stoppingPoint, a = o.heading, c = o.description, i = o.buttonText;
    return y`<calcite-block .heading=${a} .label=${a} expanded .description=${c}>${r?.length ? y`<calcite-button class="clear-button" slot=actions-end appearance=transparent .label=${t.buttons.clear} @click=${() => this._handleClearButtonClick()}>${t.buttons.clear}</calcite-button><arcgis-utility-network-trace-location-list .traceLocations=${r} .traceLocationType=${e} .view=${s}></arcgis-utility-network-trace-location-list>` : null}<div class="button-container"><calcite-button .loading=${this.isSelectWaiting} class="add-location-button" icon-start=select appearance=outline .label=${i} @click=${() => this._handleAddButtonClick()}>${i}</calcite-button></div></calcite-block>`;
  }
  render() {
    return y`<div class="root">${this.renderAddLocationBlock()}</div>`;
  }
}
k("arcgis-utility-network-trace-location", R);
export {
  R as ArcgisUtilityNetworkTraceLocation
};
