/* COPYRIGHT Esri - https://js.arcgis.com/5.2/LICENSE.txt */
import { c as B } from "../../chunks/runtime.js";
import { css as H, html as o } from "lit";
import { debounce as A } from "@arcgis/toolkit/function";
import { LitElement as k, renderElement as q, safeClassMap as x } from "@arcgis/lumina";
import { templateHasKey as D, stripHTML as E } from "@arcgis/core/applications/Components/stringUtils.js";
import { renderingSanitizer as N } from "@arcgis/core/applications/Components/sanitizerUtils.js";
import { isRelatableFeatureSupportedLayer as K, findRelatedLayer as W } from "@arcgis/core/applications/Components/featureUtils.js";
import { substitute as Z, formatNumber as O } from "@arcgis/core/intl.js";
import { watch as f, on as z } from "@arcgis/core/core/reactiveUtils.js";
import { o as G } from "../../chunks/feature-utils.js";
import M from "@arcgis/core/core/Collection.js";
import S from "@arcgis/core/rest/support/RelationshipQuery.js";
import { ignoreAbortErrors as L } from "@arcgis/core/core/promiseUtils.js";
import { classes as V } from "@arcgis/toolkit/dom";
import { createRef as J, ref as U } from "lit/directives/ref.js";
import X from "@arcgis/core/popup/Feature.js";
const Y = H`:host{position:relative;flex:1 1 auto}.list{min-height:var(--calcite-spacing-xxxl)}.list-item-hidden{display:none}.feature-observer{position:relative;bottom:var(--calcite-spacing-xxl);z-index:2;text-align:center}.sticky-loading-container{display:flex;position:sticky;bottom:var(--calcite-spacing-sm);align-items:center;justify-content:center;z-index:2;margin:0;padding:0;height:var(--calcite-spacing-xxxl);pointer-events:none}`, ee = (g) => {
  const e = [];
  if (g.formTemplate) {
    const { description: t, title: r } = g.formTemplate;
    g.fields?.forEach((i) => {
      const s = r && D(r, i.name), a = t && D(t, i.name);
      (s || a) && e.push(i.name);
    });
  }
  return e;
}, R = 100;
class te extends k {
  constructor() {
    super(...arguments), this._increaseFeaturePage = () => {
      const { state: e, showAllEnabled: t, relatedFeatures: r, featuresPerPage: i, featurePage: s } = this;
      e === "ready" && t && r.length >= i * s && this.featurePage++;
    }, this._relatedFeatureIntersectionObserver = new IntersectionObserver(([e]) => {
      e?.isIntersecting && this._increaseFeaturePage();
    }, {
      root: window.document
    }), this._featurePage = 1, this._cancelQuery = () => {
      const { _queryAbortController: e } = this;
      e && e.abort(), this._queryAbortController = null;
    }, this._cancelQueryFeatureCount = () => {
      const { _queryFeatureCountAbortController: e } = this;
      e && e.abort(), this._queryFeatureCountAbortController = null;
    }, this._cancelQueryPage = () => {
      const { _queryPageAbortController: e } = this;
      e && e.abort(), this._queryPageAbortController = null;
    }, this._queryController = async () => {
      this._cancelQuery();
      const e = new AbortController();
      this._queryAbortController = e, await L(this._query()), this._queryAbortController === e && (this._queryAbortController = null);
    }, this._queryFeatureCountController = async () => {
      this._loaded = !1, this._cancelQueryFeatureCount();
      const e = new AbortController();
      this._queryFeatureCountAbortController = e, await L(this._queryFeatureCount()), this._queryFeatureCountAbortController === e && (this._queryFeatureCountAbortController = null), this._loaded = !0;
    }, this._queryPageController = async () => {
      const e = new AbortController();
      this._queryPageAbortController = e, await L(this._queryPage()), this._queryPageAbortController === e && (this._queryPageAbortController = null);
    }, this._queryDebounced = A(this._queryController, R), this._queryFeatureCountDebounced = A(this._queryFeatureCountController, R), this._queryPageDebounced = A(this._queryPageController, R), this._query = async () => {
      const { _queryAbortController: e, relatedFeatures: t } = this;
      !this.featureCount || this.relatedLayer?.type === "subtype-group" && !this.activeCategory || (this.relatedFeatureViewModels.destroyAll(), this.featurePage = 1, t.destroyAll(), t.addMany(this._sliceFeatures(await this._queryRelatedFeatures({ signal: e?.signal }))));
    }, this._addFlowItem = (e) => {
      e && this.flowItems?.push(e);
    }, this._relatedFeatureIntersectionObserverNode = J(), this.relatedFeatures = new M(), this._queryAbortController = null, this._queryPageAbortController = null, this._queryFeatureCountAbortController = null, this.featureCount = 0, this._loaded = !1, this.relatedFeatureViewModels = new M(), this.autoDestroyDisabled = !1, this.featuresPerPage = 10, this.useFeatureNextFlowItem = !1, this.flowType = "feature-relationship", this.headingLevel = 2, this.hideHeading = !1, this.hideDescription = !1, this.showAllEnabled = !1;
  }
  static {
    this.properties = { allCategories: 16, _queryAbortController: 16, _queryPageAbortController: 16, _queryFeatureCountAbortController: 16, featureCount: 16, _loaded: 16, canLoad: 16, canQuery: 16, displayShowAllButton: 16, displayListItems: 16, categories: 16, itemDescriptionFieldName: 16, relatedFeatureViewModels: 16, state: 16, autoDestroyDisabled: 5, allItemsDescription: 32, featurePage: 9, featuresPerPage: 9, flowItems: 0, useFeatureNextFlowItem: 5, flowType: 1, headingLevel: 9, messages: 0, heading: 1, description: 1, values: 0, activeCategory: 0, hideHeading: 5, hideDescription: 5, displayCount: 9, graphic: 0, layer: 0, map: 0, view: 0, spatialReference: 0, timeZone: 1, orderByFields: 0, relationshipId: 9, showAllEnabled: 5, label: 3 };
  }
  static {
    this.styles = Y;
  }
  get orderByFieldsFixedCasing() {
    const { orderByFields: e, relatedLayer: t } = this;
    return e && t?.loaded ? e.map((r) => {
      const i = r.clone();
      return i.field = G(r.field, t), i;
    }) : e ?? [];
  }
  get supportsCacheHint() {
    return !!this.layer?.capabilities?.queryRelated?.supportsCacheHint;
  }
  get allCategoriesCount() {
    return this.allCategories?.length ?? 0;
  }
  get objectId() {
    return (this.objectIdField && this.graphic?.attributes?.[this.objectIdField]) ?? null;
  }
  get objectIdField() {
    return this.layer?.objectIdField || null;
  }
  get relatedLayer() {
    const { layer: e, map: t, relationship: r } = this;
    if (!e?.loaded || !t || !r)
      return null;
    const i = e.type === "subtype-sublayer" && e.parent && K(e.parent) ? e.parent : e;
    return W(t, i, r) ?? null;
  }
  get relatedLayerKeyField() {
    const { relatedLayer: e, relationshipId: t } = this;
    return e?.loaded && t != null ? e.relationships?.find((r) => r.id === t)?.keyField : null;
  }
  get relatedLayerKeyFields() {
    const { relatedLayer: e } = this;
    return e?.loaded ? e.relationships?.map((t) => t.keyField).filter((t) => t != null) ?? [] : [];
  }
  get relationship() {
    const { relationshipId: e, layer: t } = this;
    return e != null && t?.loaded ? t.relationships?.find(({ id: r }) => r === e) ?? null : null;
  }
  get relationshipKey() {
    const { relationshipKeyField: e } = this;
    return (e && this.graphic?.attributes?.[e]) ?? null;
  }
  get relationshipKeyField() {
    return this.relationship?.keyField || null;
  }
  get canLoad() {
    return !!this.map && this.relationshipId != null && typeof this.objectId == "number";
  }
  get canQuery() {
    const e = this.layer?.capabilities?.queryRelated;
    return !!this.relatedLayer && !!this.relationship && this.relationshipId != null && this.objectId != null && !!e?.supportsCount && e?.supportsPagination;
  }
  get displayShowAllButton() {
    const { showAllEnabled: e, featureCount: t, displayCount: r, state: i, allCategoriesCount: s } = this, a = !!s && (s > r || r === 0), n = !!t && (t > r || r === 0);
    return !e && i === "ready" && (a || n);
  }
  get displayListItems() {
    const { relatedFeatures: e, allCategoriesCount: t } = this;
    return this.displayShowAllButton || !!e.length || !!t;
  }
  get categories() {
    const { allCategories: e } = this;
    return this.showAllEnabled ? e : e?.slice(0, this.displayCount) ?? null;
  }
  get itemDescriptionFieldName() {
    return this.orderByFieldsFixedCasing[0]?.field || null;
  }
  get state() {
    const { _queryAbortController: e, _queryFeatureCountAbortController: t, _queryPageAbortController: r, canQuery: i, _loaded: s, canLoad: a } = this;
    return t || a && !s ? "loading" : e || r ? "querying" : i ? "ready" : "disabled";
  }
  get allItemsDescription() {
    const { messages: e, featureCount: t, allCategories: r, allCategoriesCount: i } = this;
    return Z(e?.numberRecords ?? "", {
      number: O(r ? i : t)
    });
  }
  get featurePage() {
    return this._featurePage;
  }
  set featurePage(e) {
    const { featuresPerPage: t, featureCount: r } = this, i = 1, s = Math.ceil(r / t) || 1;
    this._featurePage = Math.min(Math.max(e, i), s);
  }
  get heading() {
    const { activeCategory: e } = this;
    return this._heading ?? e?.name;
  }
  set heading(e) {
    this._heading = e;
  }
  get displayCount() {
    return this._displayCount ?? 3;
  }
  set displayCount(e) {
    this._displayCount = Math.min(Math.max(e ?? 3, 0), 10);
  }
  async destroy() {
    await this.manager.destroy();
  }
  loaded() {
    this.manager.onLifecycle(() => [
      f(() => [
        this.displayCount,
        this.graphic,
        this.layer,
        this.layer?.loaded,
        this.map,
        this.orderByFields,
        this.relationshipId,
        this.featuresPerPage,
        this.showAllEnabled,
        this.canQuery,
        this.featureCount,
        this.activeCategory
      ], () => this._queryDebounced(), { initial: !0 }),
      f(() => [this.featurePage, this.showAllEnabled], () => this._queryPageDebounced()),
      f(() => [this.layer, this.relationshipId, this.objectId, this.canQuery, this.activeCategory], () => this._queryFeatureCountDebounced(), { initial: !0 }),
      f(() => [this.state, this.showAllEnabled, this._relatedFeatureIntersectionObserverNode], () => this._handleRelatedFeatureObserverChange()),
      z(() => this.relatedFeatures, "change", () => this._setRelatedFeaturesViewModels())
    ]), this.manager.onDestroy(() => {
      this.relatedFeatureViewModels.destroyAll(), this.relatedFeatures.destroyAll(), this._cancelQuery(), this._cancelQueryFeatureCount(), this._cancelQueryPage(), this._unobserveRelatedFeatureObserver();
    });
  }
  async _queryFeatureCount() {
    const { layer: e, relatedLayer: t } = this;
    await e?.load(), await t?.load();
    const { _queryFeatureCountAbortController: r, activeCategory: i, canQuery: s, objectId: a, relatedLayerKeyField: n, relationshipId: l, relationshipKey: d, supportsCacheHint: b } = this;
    if (!s || !e || !t || a == null) {
      this.featureCount = 0, this.allCategories = void 0;
      return;
    }
    if (t?.type === "subtype-group" && !i) {
      if (this.featureCount = 0, this.relatedFeatureViewModels.destroyAll(), this.featurePage = 1, this.relatedFeatures.destroyAll(), n && d != null) {
        const { default: C } = await import("@arcgis/core/smartMapping/statistics/uniqueValues.js"), { uniqueValueInfos: w } = await C({
          layer: t,
          sqlWhere: `${n} = '${d}'`,
          field: t.subtypeField ?? void 0,
          signal: r?.signal
        }), v = w.map(({ count: h, value: y }) => {
          const m = t.subtypes?.find((I) => I.code === y)?.name;
          return y != null && m ? {
            count: h,
            value: y,
            name: m
          } : void 0;
        }).filter((h) => h != null);
        this.allCategories = v;
      }
      return;
    }
    const { historicMoment: p, gdbVersion: F } = e, _ = new S({
      cacheHint: b,
      gdbVersion: F,
      historicMoment: p,
      relationshipId: l,
      returnGeometry: !1,
      objectIds: [a],
      where: this._getRelationshipWhereClause(t)
    }), c = await e.queryRelatedFeaturesCount(_, {
      signal: r?.signal
    });
    this.allCategories = void 0, this.featureCount = c[a] || 0;
  }
  _getRelationshipWhereClause(e) {
    const { activeCategory: t } = this, r = e.createQuery(), i = "subtypeField" in e ? e.subtypeField : void 0, s = t && i ? `${i} = ${t.value}` : void 0, a = r.where;
    return a && s ? `(${a}) AND (${s})` : a ?? s;
  }
  _sliceFeatures(e) {
    const { showAllEnabled: t, displayCount: r } = this;
    return t ? e : r ? e.slice(0, r) : [];
  }
  async _queryPage() {
    const { relatedFeatures: e, featurePage: t, showAllEnabled: r, _queryPageAbortController: i, featureCount: s } = this;
    !r || t < 2 || !s || this.relatedLayer?.type === "subtype-group" && !this.activeCategory || e.addMany(await this._queryRelatedFeatures({ signal: i?.signal }));
  }
  async _queryRelatedFeatures(e) {
    const { displayCount: t, featureCount: r, featurePage: i, featuresPerPage: s, layer: a, orderByFieldsFixedCasing: n, relatedLayer: l, relatedLayerKeyFields: d, relationshipId: b, showAllEnabled: p, supportsCacheHint: F } = this, { canQuery: _, objectId: c } = this;
    if (!_ || !a || !l || c == null)
      return [];
    const C = p ? ((i - 1) * s + r) % r : 0, w = p ? s : t, v = l.objectIdField, h = "subtypeField" in l ? l.subtypeField : void 0, y = [
      ...n.map((u) => u.field),
      ...ee(l),
      ...d,
      v,
      h
    ].filter((u) => u != null), m = n.map((u) => `${u.field} ${u.order}`), { historicMoment: I, gdbVersion: Q } = a, j = new S({
      orderByFields: m,
      start: C,
      num: w,
      outFields: y,
      cacheHint: F,
      historicMoment: I,
      gdbVersion: Q,
      relationshipId: b,
      returnGeometry: !1,
      objectIds: [c],
      where: this._getRelationshipWhereClause(l)
    }), $ = (await a.queryRelatedFeatures(j, {
      signal: e?.signal
    }))[c]?.features || [];
    return l.type === "subtype-group" && h ? $.forEach((u) => {
      const T = u.attributes[h], P = l.findSublayerForSubtypeCode?.(T);
      u.sourceLayer = P, u.layer = P;
    }) : $.forEach((u) => {
      u.sourceLayer = l, u.layer = l;
    }), $;
  }
  _selectCategory(e) {
    const { flowItems: t } = this;
    t && this._addRelationshipFlowItem({ showAllEnabled: !0, activeCategory: e });
  }
  _selectRecord(e) {
    const { flowItems: t } = this;
    if (!t)
      return;
    const r = this.useFeatureNextFlowItem ? q(o`<arcgis-feature-next .autoDestroyDisabled=${this.autoDestroyDisabled} .flowItems=${t} .flowType=${this.flowType} .graphic=${e.graphic} .map=${this.map} show-relationship-content .spatialReference=${this.spatialReference} .timeZone=${this.timeZone} .view=${this.view}></arcgis-feature-next>`) : q(o`<arcgis-feature .autoDestroyDisabled=${this.autoDestroyDisabled} .flowItems=${t} .flowType=${this.flowType} .graphic=${e.graphic} .map=${this.map} show-relationship-content .spatialReference=${this.spatialReference} .timeZone=${this.timeZone} .view=${this.view}></arcgis-feature>`);
    this._addFlowItem(r);
  }
  _addRelationshipFlowItem({ showAllEnabled: e = !1, activeCategory: t }) {
    this._addFlowItem(q(o`<arcgis-feature-relationship .autoDestroyDisabled=${this.autoDestroyDisabled} .messages=${this.messages} .activeCategory=${t} .displayCount=${this.displayCount} .flowItems=${this.flowItems} .flowType=${this.flowType} .graphic=${this.graphic} .heading=${this.heading} hide-description .showAllEnabled=${e} hide-heading .layer=${this.layer} .map=${this.map} .orderByFields=${this.orderByFields} .relationshipId=${this.relationshipId} .spatialReference=${this.spatialReference} .useFeatureNextFlowItem=${this.useFeatureNextFlowItem} .values=${this.values} .view=${this.view}></arcgis-feature-relationship>`));
  }
  _showAllRecords() {
    const { flowItems: e } = this;
    e && this._addRelationshipFlowItem({ showAllEnabled: !0 });
  }
  _handleRelatedFeatureObserverChange() {
    this._unobserveRelatedFeatureObserver();
    const { state: e, showAllEnabled: t } = this;
    this._relatedFeatureIntersectionObserverNode.value && e === "ready" && t && this._relatedFeatureIntersectionObserver.observe(this._relatedFeatureIntersectionObserverNode.value);
  }
  _unobserveRelatedFeatureObserver() {
    this._relatedFeatureIntersectionObserverNode.value && this._relatedFeatureIntersectionObserver.unobserve(this._relatedFeatureIntersectionObserverNode.value);
  }
  _matchesFeature(e, t) {
    const r = e?.graphic?.getObjectId(), i = t?.getObjectId();
    return r != null && i != null && r === i;
  }
  _setRelatedFeaturesViewModels() {
    const { relatedFeatures: e, relatedFeatureViewModels: t, map: r, view: i, spatialReference: s, timeZone: a } = this;
    e?.filter(Boolean).forEach((n) => {
      t.some((d) => this._matchesFeature(d, n)) || t.add(new X({
        abilities: { relationshipContent: !1 },
        map: r,
        view: i,
        spatialReference: s,
        timeZone: a,
        graphic: n
      }));
    }), t.forEach((n) => {
      e?.find((d) => this._matchesFeature(n, d)) || t.remove(n);
    });
  }
  render() {
    const { state: e } = this;
    return o`<div class="root"><arcgis-feature-element-info .heading=${this.heading} .headingLevel=${this.headingLevel} .description=${this.description}></arcgis-feature-element-info>${e === "loading" ? this._renderLoading() : e === "disabled" ? this._renderRelationshipNotFound() : this._renderRelatedFeatures()}</div>`;
  }
  _renderStickyLoading() {
    return this.state === "querying" ? o`<div class="sticky-loading-container">${this._renderLoadingIcon()}</div>` : null;
  }
  _renderLoadingIcon() {
    return o`<calcite-loader inline label></calcite-loader>`;
  }
  _renderLoading() {
    return o`<div class="loading-container">${this._renderLoadingIcon()}</div>`;
  }
  _renderShowAllIconNode() {
    return o`<calcite-icon icon=list scale=s slot=content-end></calcite-icon>`;
  }
  _renderChevronIconNode() {
    return o`<calcite-icon flip-rtl icon=chevron-right scale=s slot=content-end></calcite-icon>`;
  }
  _renderCategory(e) {
    const { count: t, name: r } = e, i = O(t);
    return o`<calcite-list-item class="list-item" .disabled=${!t} .label=${r} @calciteListItemSelect=${() => this._selectCategory(e)}><calcite-chip .label=${i} scale=s slot=content-end>${i}</calcite-chip>${this._renderChevronIconNode()}</calcite-list-item>`;
  }
  _renderRelatedFeature(e) {
    const { itemDescriptionFieldName: t, values: r } = this, { formattedAttributes: i, state: s, heading: a } = e, n = {
      ...r,
      ...i?.global
    }, l = (t && n?.[t]) ?? "";
    return o`<calcite-list-item class=${x(V("list-item", { "list-item-hidden": s === "loading" }))} .description=${E(l.toString())} .label=${E(a)} @calciteListItemSelect=${() => this._selectRecord(e)}><div slot=heading><div .innerHTML=${N.sanitize(a ?? "") ?? ""}></div></div><div slot=description><div .innerHTML=${N.sanitize(l ?? "") ?? ""}></div></div>${this._renderChevronIconNode()}</calcite-list-item>`;
  }
  _renderShowAllListItem() {
    return this.displayShowAllButton ? o`<calcite-list-item .description=${this.allItemsDescription} .label=${this.messages?.showAll} @calciteListItemSelect=${() => this._showAllRecords()}>${this._renderShowAllIconNode()}</calcite-list-item>` : null;
  }
  _renderNoRelatedFeaturesMessage() {
    return o`<calcite-notice icon=information kind=brand open scale=s width=full><div slot=message>${this.messages?.noRelatedFeatures}</div></calcite-notice>`;
  }
  _renderFeatureObserver() {
    return o`<div class="feature-observer" ${U(this._relatedFeatureIntersectionObserverNode)}></div>`;
  }
  _renderList() {
    const { relatedFeatureViewModels: e, categories: t } = this;
    return o`<calcite-list display-mode=flat .label=${this.messages?.relatedFeaturesList ?? ""}>${t?.map((r) => this._renderCategory(r)) ?? e.toArray().map((r) => this._renderRelatedFeature(r))}${this._renderShowAllListItem()}</calcite-list>`;
  }
  _renderRelatedFeatures() {
    const { displayListItems: e } = this, { state: t } = this;
    return o`<div class=${x(V("list", {
      "list-querying": t === "querying"
    }))}>${e ? this._renderList() : t === "ready" ? this._renderNoRelatedFeaturesMessage() : null}${this._renderStickyLoading()}${this._renderFeatureObserver()}</div>`;
  }
  _renderRelationshipNotFound() {
    return o`<calcite-notice icon=exclamation-mark-triangle kind=danger open scale=s width=full><div slot=message>${this.messages?.relationshipNotFound}</div></calcite-notice>`;
  }
}
B("arcgis-feature-relationship", te);
export {
  te as ArcgisFeatureRelationship
};
