/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { css, html } from "lit";
import { LitElement, createEvent, setAttribute } from "@arcgis/lumina";
import { i as focusElement, n as nodeListToArray, a as slotChangeGetAssignedElements } from "../../chunks/dom.js";
import { t as toAriaBoolean } from "../../chunks/aria.js";
function isTreeItem(element) {
  return element?.tagName === "CALCITE-TREE-ITEM";
}
function getTraversableItems(root) {
  return Array.from(root.querySelectorAll("calcite-tree-item:not([disabled])")).filter(
    (item) => {
      let currentItem = item;
      while (currentItem !== root && currentItem !== null) {
        const parent = currentItem.parentElement ?? void 0;
        const traversable = !isTreeItem(parent) || !parent.hasChildren || parent.expanded;
        if (!traversable) {
          return false;
        }
        currentItem = currentItem.parentElement;
      }
      return true;
    }
  );
}
const styles = css`:host{display:block}:host(:focus){outline:2px solid transparent;outline-offset:2px}:host([hidden]){display:none}[hidden]{display:none}`;
class Tree extends LitElement {
  constructor() {
    super();
    this.items = [];
    this.child = false;
    this.lines = false;
    this.parentExpanded = false;
    this.scale = "m";
    this.selectedItems = [];
    this.selectionMode = "single";
    this.calciteTreeSelect = createEvent({ cancelable: false });
    this.listen("focus", this.onFocus);
    this.listen("focusin", this.onFocusIn);
    this.listen("focusout", this.onFocusOut);
    this.listen("calciteInternalTreeItemSelect", this.onInternalTreeItemSelect);
    this.listen("keydown", this.keyDownHandler);
  }
  static {
    this.properties = { child: [7, {}, { reflect: true, type: Boolean }], lines: [7, {}, { reflect: true, type: Boolean }], parentExpanded: [5, {}, { type: Boolean }], scale: [3, {}, { reflect: true }], selectedItems: [0, {}, { attribute: false }], selectionMode: [3, {}, { reflect: true }] };
  }
  static {
    this.styles = styles;
  }
  willUpdate(changes) {
    if (changes.has("parentExpanded") && (this.hasUpdated || this.parentExpanded !== false)) {
      this.updateItems();
    }
    const parent = this.el.parentElement?.closest("calcite-tree") ?? void 0;
    this.lines = parent ? parent.lines : this.lines;
    this.scale = parent ? parent.scale : this.scale;
    this.selectionMode = parent ? parent.selectionMode : this.selectionMode;
    this.child = !!parent;
  }
  onFocus() {
    if (!this.child) {
      const focusTarget = (this.el.querySelector("calcite-tree-item[selected]:not([disabled])") || this.el.querySelector("calcite-tree-item:not([disabled])")) ?? void 0;
      focusElement(focusTarget, true, "focusable");
    }
  }
  onFocusIn(event) {
    const focusedFromRootOrOutsideTree = event.relatedTarget === this.el || !this.el.contains(event.relatedTarget);
    if (focusedFromRootOrOutsideTree) {
      this.el.removeAttribute("tabindex");
    }
  }
  onFocusOut(event) {
    const willFocusOutsideTree = !this.el.contains(event.relatedTarget);
    if (willFocusOutsideTree) {
      this.el.tabIndex = this.getRootTabIndex();
    }
  }
  onInternalTreeItemSelect(event) {
    if (this.child) {
      return;
    }
    const target = event.target;
    const childItems = nodeListToArray(target.querySelectorAll("calcite-tree-item"));
    event.preventDefault();
    event.stopPropagation();
    if (this.selectionMode === "ancestors") {
      this.updateAncestorTree(event);
      return;
    }
    const isNoneSelectionMode = this.selectionMode === "none";
    const shouldSelect = this.selectionMode !== null && (!target.hasChildren || target.hasChildren && (this.selectionMode === "children" || this.selectionMode === "multichildren"));
    const shouldDeselectAllChildren = this.selectionMode === "multichildren" && target.hasChildren;
    const shouldModifyToCurrentSelection = !isNoneSelectionMode && event.detail.modifyCurrentSelection && (this.selectionMode === "multiple" || this.selectionMode === "multichildren");
    const shouldClearCurrentSelection = !shouldModifyToCurrentSelection && ((this.selectionMode === "single" || this.selectionMode === "multiple") && childItems.length <= 0 || this.selectionMode === "children" || this.selectionMode === "multichildren" || this.selectionMode === "single-persist" && !target.hasChildren);
    const shouldUpdateExpand = ["multiple", "none", "single", "single-persist"].includes(this.selectionMode) && target.hasChildren;
    const targetItems = [];
    if (shouldSelect) {
      targetItems.push(target);
    }
    if (shouldClearCurrentSelection) {
      const selectedItems = nodeListToArray(this.el.querySelectorAll("calcite-tree-item[selected]"));
      selectedItems.forEach((treeItem) => {
        if (!targetItems.includes(treeItem)) {
          treeItem.selected = false;
        }
      });
    }
    if (shouldUpdateExpand && ["multiple", "none", "single", "single-persist"].includes(this.selectionMode)) {
      target.expanded = !target.expanded;
    }
    if (shouldDeselectAllChildren) {
      childItems.forEach((item) => {
        item.selected = false;
        if (item.hasChildren) {
          item.expanded = false;
        }
      });
    }
    if (shouldModifyToCurrentSelection) {
      window.getSelection().removeAllRanges();
    }
    if (shouldModifyToCurrentSelection && target.selected) {
      targetItems.forEach((treeItem) => {
        if (!treeItem.disabled) {
          treeItem.selected = false;
        }
      });
    } else if (!isNoneSelectionMode) {
      targetItems.forEach((treeItem) => {
        if (!treeItem.disabled) {
          treeItem.selected = this.selectionMode !== "single" || !treeItem.selected;
        }
      });
    }
    this.selectedItems = isNoneSelectionMode ? [] : nodeListToArray(this.el.querySelectorAll("calcite-tree-item")).filter((i) => i.selected);
    this.calciteTreeSelect.emit();
    event.stopPropagation();
  }
  keyDownHandler(event) {
    if (this.child) {
      return;
    }
    const root = this.el;
    const target = event.target;
    const supportedKeys = ["ArrowRight", "ArrowDown", "ArrowLeft", "ArrowUp", "Home", "End", "Tab"];
    if (!(isTreeItem(target) && this.el.contains(target)) || !supportedKeys.includes(event.key)) {
      return;
    }
    const traversableItems = getTraversableItems(root);
    if (event.key === "Tab") {
      traversableItems.forEach((item) => item.tabIndex = -1);
      return;
    }
    if (event.key === "ArrowDown") {
      const currentItemIndex = traversableItems.indexOf(target);
      const nextItem = traversableItems[currentItemIndex + 1];
      nextItem?.focus();
      event.preventDefault();
      return;
    }
    if (event.key === "ArrowUp") {
      const currentItemIndex = traversableItems.indexOf(target);
      const previousItem = traversableItems[currentItemIndex - 1];
      previousItem?.focus();
      event.preventDefault();
      return;
    }
    if (event.key === "ArrowLeft") {
      if (target.hasChildren && target.expanded) {
        target.expanded = false;
        event.preventDefault();
        return;
      }
      const rootToItemPath = traversableItems.slice(0, traversableItems.indexOf(target)).reverse();
      const parentItem = rootToItemPath.find((item) => item.depth === target.depth - 1);
      parentItem?.focus();
      event.preventDefault();
      return;
    }
    if (event.key === "ArrowRight") {
      if (!target.disabled && target.hasChildren) {
        if (!target.expanded) {
          target.expanded = true;
          event.preventDefault();
        } else {
          const currentItemIndex = traversableItems.indexOf(target);
          const nextItem = traversableItems[currentItemIndex + 1];
          nextItem?.focus();
          event.preventDefault();
        }
      }
      return;
    }
    if (event.key === "Home") {
      const firstNode = traversableItems.shift();
      if (firstNode) {
        firstNode.focus();
        event.preventDefault();
      }
      return;
    }
    if (event.key === "End") {
      const lastNode = traversableItems.pop();
      if (lastNode) {
        lastNode.focus();
        event.preventDefault();
      }
      return;
    }
  }
  updateAncestorTree(event) {
    const item = event.target;
    const updateItem = event.detail.updateItem;
    if (item.disabled || item.indeterminate && !updateItem) {
      return;
    }
    const ancestors = [];
    let parent = item.parentElement.closest("calcite-tree-item");
    while (parent) {
      ancestors.push(parent);
      parent = parent.parentElement.closest("calcite-tree-item");
    }
    const childItems = Array.from(item.querySelectorAll("calcite-tree-item:not([disabled])"));
    const childItemsWithNoChildren = childItems.filter((child) => !child.hasChildren);
    const childItemsWithChildren = childItems.filter((child) => child.hasChildren);
    let futureSelected;
    if (updateItem) {
      futureSelected = item.hasChildren ? !(item.selected || item.indeterminate) : !item.selected;
    } else {
      futureSelected = item.selected;
    }
    childItemsWithNoChildren.forEach((el) => {
      el.selected = futureSelected;
      el.indeterminate = false;
    });
    function updateItemState(childItems2, item2) {
      const selected = childItems2.filter((child) => child.selected);
      const unselected = childItems2.filter((child) => !child.selected);
      item2.selected = selected.length === childItems2.length;
      item2.indeterminate = selected.length > 0 && unselected.length > 0;
    }
    childItemsWithChildren.reverse().forEach((el) => {
      const directChildItems = Array.from(el.querySelectorAll(":scope > calcite-tree > calcite-tree-item"));
      updateItemState(directChildItems, el);
    });
    if (updateItem) {
      if (item.hasChildren) {
        updateItemState(childItems, item);
      } else {
        item.selected = futureSelected;
        item.indeterminate = false;
      }
    }
    ancestors.forEach((ancestor) => {
      const descendants = nodeListToArray(ancestor.querySelectorAll("calcite-tree-item"));
      const activeDescendants = descendants.filter((el) => el.selected);
      if (activeDescendants.length === 0) {
        ancestor.selected = false;
        ancestor.indeterminate = false;
        return;
      }
      const indeterminate = activeDescendants.length < descendants.length;
      ancestor.indeterminate = indeterminate;
      ancestor.selected = !indeterminate;
    });
    this.selectedItems = nodeListToArray(this.el.querySelectorAll("calcite-tree-item")).filter((i) => i.selected);
    if (updateItem) {
      this.calciteTreeSelect.emit();
    }
  }
  updateItems() {
    this.items.forEach((item) => item.parentExpanded = this.parentExpanded);
  }
  handleDefaultSlotChange(event) {
    const items = slotChangeGetAssignedElements(event).filter((el) => el.matches("calcite-tree-item"));
    this.items = items;
    this.updateItems();
  }
  getRootTabIndex() {
    return !this.child ? 0 : -1;
  }
  render() {
    this.el.ariaMultiSelectable = this.child ? null : toAriaBoolean(this.selectionMode === "multiple" || this.selectionMode === "multichildren");
    this.el.role = !this.child ? "tree" : null;
    setAttribute(this.el, "tabIndex", this.getRootTabIndex());
    return html`<slot @slotchange=${this.handleDefaultSlotChange}></slot>`;
  }
}
customElement("calcite-tree", Tree);
export {
  Tree
};
