import { c as H } from "../../chunks/runtime.js";
import { css as K, html as n } from "lit";
import { keyed as O } from "lit/directives/keyed.js";
import { debounce as R } from "@arcgis/toolkit/function";
import { LitElement as W, renderElement as D, safeClassMap as g } from "@arcgis/lumina";
import { templateHasKey as S, stripHTML as N } from "@arcgis/core/applications/Components/stringUtils.js";
import { isRelatableFeatureSupportedLayer as Z, findRelatedLayer as z } from "@arcgis/core/applications/Components/featureUtils.js";
import { substitute as G, formatNumber as V } from "@arcgis/core/intl.js";
import { watch as C, on as J } from "@arcgis/core/core/reactiveUtils.js";
import { a as U } from "../../chunks/feature-utils.js";
import Q from "@arcgis/core/core/Collection.js";
import M from "@arcgis/core/rest/support/RelationshipQuery.js";
import { ignoreAbortErrors as P } from "@arcgis/core/core/promiseUtils.js";
import X from "@arcgis/core/widgets/Feature/FeatureViewModel.js";
import { classes as j } from "@arcgis/toolkit/dom";
import { createRef as Y, ref as ee } from "lit/directives/ref.js";
/*! All material copyright Esri, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.34/esri/copyright.txt for details.
v4.34.7 */
const te = K`:host{position:relative;flex:1 1 auto}.arcgis-feature-relationship__list{min-height:var(--calcite-spacing-xxxl)}.arcgis-feature-relationship__list-item--hidden{display:none}.arcgis-feature-relationship__feature-observer{position:relative;bottom:var(--calcite-spacing-xxl);z-index:2;text-align:center}.arcgis-feature-relationship__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}`, re = (m) => {
  const e = [];
  if (m.formTemplate) {
    const { description: t, title: r } = m.formTemplate;
    m.fields?.forEach((s) => {
      const i = r && S(r, s.name), a = t && S(t, s.name);
      (i || a) && e.push(s.name);
    });
  }
  return e;
}, x = 100, se = "arcgis-feature", h = `${se}-relationship`, c = {
  // widget
  base: h,
  listContainer: `${h}__list`,
  listItem: `${h}__list-item`,
  listItemHidden: `${h}__list-item--hidden`,
  listContainerQuerying: `${h}__list--querying`,
  featureObserver: `${h}__feature-observer`,
  // loading
  stickySpinnerContainer: `${h}__sticky-loading-container`,
  loadingSpinnerContainer: `${h}__loading-container`
};
class ie extends W {
  constructor() {
    super(...arguments), this._increaseFeaturePage = () => {
      const { state: e, showAllEnabled: t, relatedFeatures: r, featuresPerPage: s, featurePage: i } = this;
      e === "ready" && t && r.length >= s * i && 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 P(this._query()), this._queryAbortController === e && (this._queryAbortController = null);
    }, this._queryFeatureCountController = async () => {
      this._loaded = !1, this._cancelQueryFeatureCount();
      const e = new AbortController();
      this._queryFeatureCountAbortController = e, await P(this._queryFeatureCount()), this._queryFeatureCountAbortController === e && (this._queryFeatureCountAbortController = null), this._loaded = !0;
    }, this._queryPageController = async () => {
      const e = new AbortController();
      this._queryPageAbortController = e, await P(this._queryPage()), this._queryPageAbortController === e && (this._queryPageAbortController = null);
    }, this._queryDebounced = R(this._queryController, x), this._queryFeatureCountDebounced = R(this._queryFeatureCountController, x), this._queryPageDebounced = R(this._queryPageController, x), 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 = Y(), this.relatedFeatures = new Q(), this._queryAbortController = null, this._queryPageAbortController = null, this._queryFeatureCountAbortController = null, this.featureCount = 0, this._loaded = !1, this.relatedFeatureViewModels = new Q(), this.autoDestroyDisabled = !1, this.featuresPerPage = 10, 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, 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 = te;
  }
  get orderByFieldsFixedCasing() {
    const { orderByFields: e, relatedLayer: t } = this;
    return e && t?.loaded ? e.map((r) => {
      const s = r.clone();
      return s.field = U(r.field, t), s;
    }) : 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 s = e.type === "subtype-sublayer" && e.parent && Z(e.parent) ? e.parent : e;
    return z(t, s, 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: s, allCategoriesCount: i } = this, a = !!i && (i > r || r === 0), o = !!t && (t > r || r === 0);
    return !e && s === "ready" && (a || o);
  }
  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: s, _loaded: i, canLoad: a } = this;
    return t || a && !i ? "loading" : e || r ? "querying" : s ? "ready" : "disabled";
  }
  get allItemsDescription() {
    const { messages: e, featureCount: t, allCategories: r, allCategoriesCount: s } = this;
    return G(e?.numberRecords ?? "", {
      number: V(r ? s : t)
    });
  }
  get featurePage() {
    return this._featurePage;
  }
  set featurePage(e) {
    const { featuresPerPage: t, featureCount: r } = this, s = 1, i = Math.ceil(r / t) || 1;
    this._featurePage = Math.min(Math.max(e, s), i);
  }
  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(() => [
      C(() => [
        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 }),
      C(() => [this.featurePage, this.showAllEnabled], () => this._queryPageDebounced()),
      C(() => [this.layer, this.relationshipId, this.objectId, this.canQuery, this.activeCategory], () => this._queryFeatureCountDebounced(), { initial: !0 }),
      C(() => [this.state, this.showAllEnabled, this._relatedFeatureIntersectionObserverNode], () => this._handleRelatedFeatureObserverChange()),
      J(() => 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: s, canQuery: i, objectId: a, relatedLayerKeyField: o, relationshipId: l, relationshipKey: d, supportsCacheHint: F } = this;
    if (!i || !e || !t || a == null) {
      this.featureCount = 0, this.allCategories = void 0;
      return;
    }
    if (t?.type === "subtype-group" && !s) {
      if (this.featureCount = 0, this.relatedFeatureViewModels.destroyAll(), this.featurePage = 1, this.relatedFeatures.destroyAll(), o && d != null) {
        const { default: I } = await import("@arcgis/core/smartMapping/statistics/uniqueValues.js"), { uniqueValueInfos: $ } = await I({
          layer: t,
          sqlWhere: `${o} = '${d}'`,
          field: t.subtypeField ?? void 0,
          signal: r?.signal
        }), A = $.map(({ count: y, value: f }) => {
          const b = t.subtypes?.find((q) => q.code === f)?.name;
          return f != null && b ? {
            count: y,
            value: f,
            name: b
          } : void 0;
        }).filter((y) => y != null);
        this.allCategories = A;
      }
      return;
    }
    const { historicMoment: _, gdbVersion: w } = e, v = new M({
      cacheHint: F,
      gdbVersion: w,
      historicMoment: _,
      relationshipId: l,
      returnGeometry: !1,
      objectIds: [a],
      where: this._getRelationshipWhereClause(t)
    }), p = await e.queryRelatedFeaturesCount(v, {
      signal: r?.signal
    });
    this.allCategories = void 0, this.featureCount = p[a] || 0;
  }
  _getRelationshipWhereClause(e) {
    const { activeCategory: t } = this, r = e.createQuery(), s = "subtypeField" in e ? e.subtypeField : void 0, i = t && s ? `${s} = ${t.value}` : void 0, a = r.where;
    return a && i ? `(${a}) AND (${i})` : a ?? i;
  }
  _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: s, featureCount: i } = this;
    !r || t < 2 || !i || this.relatedLayer?.type === "subtype-group" && !this.activeCategory || e.addMany(await this._queryRelatedFeatures({ signal: s?.signal }));
  }
  async _queryRelatedFeatures(e) {
    const { displayCount: t, featureCount: r, featurePage: s, featuresPerPage: i, layer: a, orderByFieldsFixedCasing: o, relatedLayer: l, relatedLayerKeyFields: d, relationshipId: F, showAllEnabled: _, supportsCacheHint: w } = this, { canQuery: v, objectId: p } = this;
    if (!v || !a || !l || p == null)
      return [];
    const I = _ ? ((s - 1) * i + r) % r : 0, $ = _ ? i : t, A = l.objectIdField, y = "subtypeField" in l ? l.subtypeField : void 0, f = [
      ...o.map((u) => u.field),
      ...re(l),
      ...d,
      A,
      y
    ].filter((u) => u != null), b = o.map((u) => `${u.field} ${u.order}`), { historicMoment: q, gdbVersion: k } = a, B = new M({
      orderByFields: b,
      start: I,
      num: $,
      outFields: f,
      cacheHint: w,
      historicMoment: q,
      gdbVersion: k,
      relationshipId: F,
      returnGeometry: !1,
      objectIds: [p],
      where: this._getRelationshipWhereClause(l)
    }), L = (await a.queryRelatedFeatures(B, {
      signal: e?.signal
    }))[p]?.features || [];
    return l.type === "subtype-group" && y ? L.forEach((u) => {
      const T = u.attributes[y], E = l.findSublayerForSubtypeCode?.(T);
      u.sourceLayer = E, u.layer = E;
    }) : L.forEach((u) => {
      u.sourceLayer = l, u.layer = l;
    }), L;
  }
  _selectCategory(e) {
    const { flowItems: t } = this;
    t && this._addRelationshipFlowItem({ showAllEnabled: !0, activeCategory: e });
  }
  _selectRecord(e) {
    const { flowItems: t } = this;
    t && this._addFlowItem(D(O(e, n`<arcgis-feature .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>`)));
  }
  _addRelationshipFlowItem({ showAllEnabled: e = !1, activeCategory: t }) {
    this._addFlowItem(D(O(t, n`<arcgis-feature-relationship .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} .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(), s = t?.getObjectId();
    return r != null && s != null && r === s;
  }
  _setRelatedFeaturesViewModels() {
    const { relatedFeatures: e, relatedFeatureViewModels: t, map: r, view: s, spatialReference: i, timeZone: a } = this;
    e?.filter(Boolean).forEach((o) => {
      t.some((d) => this._matchesFeature(d, o)) || t.add(new X({
        abilities: { relationshipContent: !1 },
        map: r,
        view: s,
        spatialReference: i,
        timeZone: a,
        graphic: o
      }));
    }), t.forEach((o) => {
      e?.find((d) => this._matchesFeature(o, d)) || t.remove(o);
    });
  }
  render() {
    const { state: e } = this;
    return n`<div class=${g(c.base)}><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" ? n`<div class=${g(c.stickySpinnerContainer)}>${this._renderLoadingIcon()}</div>` : null;
  }
  _renderLoadingIcon() {
    return n`<calcite-loader inline label></calcite-loader>`;
  }
  _renderLoading() {
    return n`<div class=${g(c.loadingSpinnerContainer)}>${this._renderLoadingIcon()}</div>`;
  }
  _renderShowAllIconNode() {
    return n`<calcite-icon icon=list scale=s slot=content-end></calcite-icon>`;
  }
  _renderChevronIconNode() {
    return n`<calcite-icon flip-rtl icon=chevron-right scale=s slot=content-end></calcite-icon>`;
  }
  _renderCategory(e) {
    const { count: t, name: r } = e, s = V(t);
    return n`<calcite-list-item class=${g(c.listItem)} .disabled=${!t} .label=${r} @calciteListItemSelect=${() => this._selectCategory(e)}><calcite-chip .label=${s} scale=s slot=content-end>${s}</calcite-chip>${this._renderChevronIconNode()}</calcite-list-item>`;
  }
  _renderRelatedFeature(e) {
    const { itemDescriptionFieldName: t, values: r } = this, { formattedAttributes: s, state: i, title: a } = e, o = {
      ...s?.global,
      ...r
    }, l = (t && o?.[t]) ?? "", d = i === "loading";
    return n`<calcite-list-item class=${g(j(c.listItem, { [c.listItemHidden]: d }))} .description=${N(l.toString())} .label=${N(a)} @calciteListItemSelect=${() => this._selectRecord(e)}>${this._renderChevronIconNode()}</calcite-list-item>`;
  }
  _renderShowAllListItem() {
    return this.displayShowAllButton ? n`<calcite-list-item .description=${this.allItemsDescription} .label=${this.messages?.showAll} @calciteListItemSelect=${() => this._showAllRecords()}>${this._renderShowAllIconNode()}</calcite-list-item>` : null;
  }
  _renderNoRelatedFeaturesMessage() {
    return n`<calcite-notice icon=information kind=brand open scale=s width=full><div slot=message>${this.messages?.noRelatedFeatures}</div></calcite-notice>`;
  }
  _renderFeatureObserver() {
    return n`<div class=${g(c.featureObserver)} ${ee(this._relatedFeatureIntersectionObserverNode)}></div>`;
  }
  _renderList() {
    const { relatedFeatureViewModels: e, categories: t } = this;
    return n`<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 n`<div class=${g(j(c.listContainer, {
      [c.listContainerQuerying]: t === "querying"
    }))}>${e ? this._renderList() : t === "ready" ? this._renderNoRelatedFeaturesMessage() : null}${this._renderStickyLoading()}${this._renderFeatureObserver()}</div>`;
  }
  _renderRelationshipNotFound() {
    return n`<calcite-notice icon=exclamation-mark-triangle kind=danger open scale=s width=full><div slot=message>${this.messages?.relationshipNotFound}</div></calcite-notice>`;
  }
}
H("arcgis-feature-relationship", ie);
export {
  ie as ArcgisFeatureRelationship
};
