/* COPYRIGHT Esri - https://js.arcgis.com/5.2/LICENSE.txt */
import { c as C } from "../../chunks/runtime.js";
import { css as L, html as p } from "lit";
import { LitElement as S, nothing as V } from "@arcgis/lumina";
import y from "@arcgis/core/core/Collection.js";
import m from "@arcgis/core/core/Accessor.js";
import { property as a, subclass as v } from "@arcgis/core/core/accessorSupport/decorators.js";
import { c as O, f as $ } from "../../chunks/building-layer-utils.js";
import { watch as b, on as E } from "@arcgis/core/core/reactiveUtils.js";
import { i as A } from "../../chunks/async-utils.js";
var D = Object.defineProperty, M = Object.getOwnPropertyDescriptor, d = (e, t, i, l) => {
  for (var s = l > 1 ? void 0 : l ? M(t, i) : t, r = e.length - 1, o; r >= 0; r--)
    (o = e[r]) && (s = (l ? o(t, i, s) : o(s)) || s);
  return l && s && D(t, i, s), s;
};
let n = class extends m {
  constructor(e) {
    super(e), this.id = "root", this.children = new y(), this.layers = new y(), this.level = 0, this.childIds = /* @__PURE__ */ new Set(), this.layerUniqueIds = /* @__PURE__ */ new Set();
  }
  initialize() {
    this.addHandles([
      this.layers.on("before-add", (e) => {
        this.layerUniqueIds.has(e.item.uid) ? e.preventDefault() : this.layerUniqueIds.add(e.item.uid);
      }),
      // Each time a layer is added/removed, we need to keep track of its visible
      // and title properties because the node's properties depend on them.
      this.layers.on("after-add", ({ item: e }) => {
        this.addHandles(
          [
            b(
              () => e.visible,
              () => this.notifyChange("visible"),
              { initial: !0 }
            ),
            b(
              () => e.title,
              () => this.notifyChange("title"),
              { initial: !0 }
            )
          ],
          e.uid
        );
      }),
      this.layers.on("before-remove", ({ item: e }) => {
        this.removeHandles(e.uid), this.notifyChange("title"), this.notifyChange("visible");
      }),
      this.children.on("before-add", (e) => {
        this.childIds.has(e.item.id) ? e.preventDefault() : (e.item._set("parent", this), this.childIds.add(e.item.id));
      })
    ]);
  }
  destroy() {
    this.children.forEach((e) => e.destroy());
  }
  get hasChildren() {
    return this.children.length > 0;
  }
  get isDiscipline() {
    return this.level === 1;
  }
  get visible() {
    return f(this.layers, (e) => e.visible);
  }
  get title() {
    return f(this.layers, (e) => e.title) || this.layers.map((e) => e.title).join(", ") || null;
  }
  /**
   * Toggles the visibility of all the layers controlled by this node.
   * If a value is specified, sets all the layers' visibility to that value.
   *
   * @param value
   *    The value to which the `visible` property of each layer is to be set.
   */
  toggleVisibility(e) {
    const t = e === void 0 ? !this.visible : e;
    this.layers.forEach((i) => {
      i.visible = t;
    }), t && this.parent != null && this.parent.toggleVisibility(!0);
  }
  /**
   * Toggles the visibility of all the layers controlled by this node,
   * as well as setting the visibility of all the sibling's node of this node.
   *
   * @param value
   *    The value to which the `visible` property of each layer and siblings is to be set.
   */
  toggleAllSiblingsVisibility(e) {
    const t = e === void 0 ? !this.visible : e;
    this.toggleVisibility(t), this.parent != null && (this.parent.toggleVisibility(t), this.parent.children.forEach((i) => i.toggleVisibility(t)));
  }
};
d([
  a({})
], n.prototype, "id", 2);
d([
  a()
], n.prototype, "parent", 2);
d([
  a({ readOnly: !0 })
], n.prototype, "children", 2);
d([
  a({ readOnly: !0 })
], n.prototype, "layers", 2);
d([
  a({})
], n.prototype, "level", 2);
d([
  a({ readOnly: !0 })
], n.prototype, "hasChildren", 1);
d([
  a({ readOnly: !0 })
], n.prototype, "isDiscipline", 1);
d([
  a({ readOnly: !0 })
], n.prototype, "visible", 1);
d([
  a({ readOnly: !0 })
], n.prototype, "title", 1);
n = d([
  v("esri.widgets.BuildingExplorer.support.LayerTreeNode")
], n);
function f(e, t) {
  let i = null;
  for (const l of e) {
    const s = t(l);
    if (i != null && i !== s)
      return null;
    i = s;
  }
  return i;
}
var N = Object.defineProperty, x = Object.getOwnPropertyDescriptor, _ = (e) => {
  throw TypeError(e);
}, u = (e, t, i, l) => {
  for (var s = l > 1 ? void 0 : l ? x(t, i) : t, r = e.length - 1, o; r >= 0; r--)
    (o = e[r]) && (s = (l ? o(t, i, s) : o(s)) || s);
  return l && s && N(t, i, s), s;
}, P = (e, t, i) => t.has(e) || _("Cannot " + i), g = (e, t, i) => (P(e, t, "read from private field"), i ? i.call(e) : t.get(e)), F = (e, t, i) => t.has(e) ? _("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, i), c;
let h = class extends m {
  constructor(e) {
    super(e), this.root = new n(), F(this, c, new y()), this.state = "disabled", this.loadLayers = O();
  }
  initialize() {
    this.addHandles(
      E(
        () => this.layers,
        "change",
        () => {
          this._onLayersChange();
        },
        {
          onListenerAdd: () => {
            this._onLayersChange();
          },
          onListenerRemove: () => {
            this._onLayersChange();
          }
        }
      )
    ), this._onLayersChange();
  }
  destroy() {
    this._set("state", "disabled"), this.root.destroy();
  }
  get layers() {
    return g(this, c);
  }
  set layers(e) {
    g(this, c).removeAll(), g(this, c).addMany(e);
  }
  /**
   * Initializes our internal tree with all the categories and disciplines from
   * all the layers.
   */
  updateLayerTree() {
    this.root.destroy(), this._set("root", new n());
    const e = /* @__PURE__ */ new Map(), t = this.layers.length > 1 ? "modelName" : "id";
    return this.layers.forEach((i) => {
      const l = $(i);
      this.addNodesForSublayers(l ?? i, this.root, e, t);
    }), this;
  }
  /**
   * Adds a node to control the specified layer. If a node already exists with
   * the same `id` (i.e. same `modelName`), we simply add the layer to that node.
   * This also recursively adds nodes for any sublayers.
   *
   * @param layer
   *    The layer which is to be controlled by the node.
   * @param parentNode
   *    The node to which the new nodes are to be added.
   * @param nodes
   *    Map with all the nodes already added.
   * @param matchBy
   *    The sublayer property used to deduplicate sublayers.
   */
  addNodeForLayer(e, t, i, l) {
    const s = String(e[l]).toLowerCase();
    if (s == null || e.isEmpty)
      return;
    const r = `${t.id}/${s}`;
    let o = i.get(r);
    o || (o = new n({ id: s, level: t.level + 1 }), i.set(r, o)), o.layers.push(e), t.children.push(o), this.addNodesForSublayers(e, o, i, l);
  }
  /**
   * Adds nodes for all the sublayers of the specified layer.
   *
   * @param layer
   *    The layer whose sublayers are to be traversed.
   * @param parentNode
   *    The node to which new nodes are to be added.
   * @param nodes
   *    Map with all the nodes already added.
   * @param matchBy
   *    The sublayer property used to deduplicate sublayers.
   */
  addNodesForSublayers(e, t, i, l) {
    (e.type === "building-scene" || e.type === "building-group" && !e.isEmpty) && e.sublayers.forEach((s) => this.addNodeForLayer(s, t, i, l));
  }
  /**
   * Called when the layers are changed.
   */
  async _onLayersChange() {
    if (this._set("state", "loading"), this.layers.length !== 0)
      try {
        await this.loadLayers(this.layers), this.updateLayerTree(), this._set("state", "ready");
      } catch (e) {
        A(e) || this._set("state", "failed");
      }
  }
};
c = /* @__PURE__ */ new WeakMap();
u([
  a()
], h.prototype, "root", 2);
u([
  a()
], h.prototype, "layers", 1);
u([
  a()
], h.prototype, "state", 2);
h = u([
  v("esri.components.BuildingExplorer.BuildingDisciplinesViewModel")
], h);
const T = L`.label{--calcite-label-margin-bottom: 0}`;
class B extends S {
  constructor() {
    super(...arguments), this.#e = new h(), this.toggleSiblingsVisibility = !1;
  }
  static {
    this.properties = { layers: 0, messages: 0, toggleSiblingsVisibility: 5 };
  }
  static {
    this.styles = T;
  }
  #e;
  get layers() {
    return this.#e.layers.toArray();
  }
  set layers(t) {
    this.#e.layers = new y(t);
  }
  render() {
    const t = this.messages, i = this.#e;
    return t == null ? null : p`<calcite-tree lines selection-mode=none>${w({ node: i.root, messages: t })}</calcite-tree>`;
  }
}
function I(e) {
  const t = e.node, i = t.visible === !0, l = t.visible === null, s = i ? e.messages.hideSublayer : e.messages.showSublayer;
  return p`<calcite-tree-item><calcite-label class="label" layout=inline><calcite-checkbox .checked=${i} .indeterminate=${l} .label=${s} @click=${(r) => {
    r.stopPropagation(), (r.metaKey || r.ctrlKey) && e.toggleSiblingsVisibility && (t.toggleVisibility(), t.toggleAllSiblingsVisibility());
  }} title=${s ?? V} @calciteCheckboxChange=${(r) => {
    t.toggleVisibility(r.currentTarget.checked);
  }}></calcite-checkbox>${e.node.title}</calcite-label>${e.node.hasChildren ? p`<calcite-tree lines selection-mode=none slot=children>${w({ node: e.node, messages: e.messages })}</calcite-tree>` : null}</calcite-tree-item>`;
}
function w(e) {
  return e.node.children.toArray().reverse().map((i) => I({ node: i, messages: e.messages, toggleSiblingsVisibility: e.toggleSiblingsVisibility }));
}
C("arcgis-building-discipline-tree", B);
export {
  B as BuildingDisciplineTree
};
