import { html } from 'lit';
import { state, property, query } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { live } from 'lit/directives/live.js';
import { when } from 'lit/directives/when.js';
import { stopAnimations, animateTo, shimKeyframesHeightAuto } from '../../internal/animate.mjs';
import { boolean } from '../../internal/boolean.mjs';
import FlowRdfElement from '../../internal/flow-ui-rdf-element.mjs';
import { watch } from '../../internal/watch.mjs';
import { setDefaultAnimation, getAnimation } from '../../utilities/animation-registry.mjs';
import { LocalizeController } from '../../utilities/localize.mjs';
import styles from './tree-item.styles.mjs';

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result)
    __defProp(target, key, result);
  return result;
};
const _FlowUiTreeItem = class _FlowUiTreeItem extends FlowRdfElement {
  constructor() {
    super(...arguments);
    this.localize = new LocalizeController(this);
    this.indeterminate = false;
    this.isLeaf = false;
    this.loading = false;
    this.selectable = false;
    this.value = "";
    this.expanded = false;
    this.selected = false;
    this.disabled = false;
    this.lazy = false;
    this.size = "medium";
    this.hidden = false;
  }
  /** @internal */
  static isTreeItem(node) {
    return node instanceof Element && node.getAttribute("role") === "treeitem";
  }
  connectedCallback() {
    super.connectedCallback();
    this.expanded = boolean(this.expanded, true);
    this.selected = boolean(this.selected, true);
    this.disabled = boolean(this.disabled, true);
    this.lazy = boolean(this.lazy, true);
    this.hidden = boolean(this.hidden, true);
    this.setAttribute("role", "treeitem");
    this.setAttribute("tabindex", "-1");
    if (this.isNestedItem()) {
      this.slot = "children";
    }
  }
  firstUpdated() {
    this.childrenContainer.hidden = !this.expanded;
    this.childrenContainer.style.height = this.expanded ? "auto" : "0";
    this.isLeaf = !this.lazy && this.getChildrenItems().length === 0;
    this.handleExpandedChange();
  }
  handleValueChange() {
    if (typeof this.value !== "string") {
      this.value = String(this.value);
    }
    if (this.value.includes(" ")) {
      console.error(`Option values cannot include a space. All spaces have been replaced with underscores.`, this);
      this.value = this.value.replace(/ /g, "_");
    }
  }
  async animateCollapse() {
    this.emit("flow-ui-collapse");
    await stopAnimations(this.childrenContainer);
    const { keyframes, options } = getAnimation(this, "tree-item.collapse", { dir: this.localize.dir() });
    await animateTo(
      this.childrenContainer,
      shimKeyframesHeightAuto(keyframes, this.childrenContainer.scrollHeight),
      options
    );
    this.childrenContainer.hidden = true;
    this.emit("flow-ui-after-collapse");
  }
  // Checks whether the item is nested into an item
  isNestedItem() {
    const parent = this.parentElement;
    return !!parent && _FlowUiTreeItem.isTreeItem(parent);
  }
  handleChildrenSlotChange() {
    this.loading = false;
    this.isLeaf = !this.lazy && this.getChildrenItems().length === 0;
  }
  willUpdate(changedProperties) {
    if (changedProperties.has("selected") && !changedProperties.has("indeterminate")) {
      this.indeterminate = false;
    }
  }
  async animateExpand() {
    this.emit("flow-ui-expand");
    await stopAnimations(this.childrenContainer);
    this.childrenContainer.hidden = false;
    const { keyframes, options } = getAnimation(this, "tree-item.expand", { dir: this.localize.dir() });
    await animateTo(
      this.childrenContainer,
      shimKeyframesHeightAuto(keyframes, this.childrenContainer.scrollHeight),
      options
    );
    this.childrenContainer.style.height = "auto";
    this.emit("flow-ui-after-expand");
  }
  handleLoadingChange() {
    this.setAttribute("aria-busy", this.loading ? "true" : "false");
    if (!this.loading) {
      this.animateExpand();
    }
  }
  handleDisabledChange() {
    this.setAttribute("aria-disabled", this.disabled ? "true" : "false");
  }
  handleSelectedChange() {
    this.setAttribute("aria-selected", this.selected ? "true" : "false");
  }
  handleExpandedChange() {
    if (!this.isLeaf) {
      this.setAttribute("aria-expanded", this.expanded ? "true" : "false");
    } else {
      this.removeAttribute("aria-expanded");
    }
  }
  handleExpandAnimation() {
    if (this.expanded) {
      if (this.lazy) {
        this.loading = true;
        this.emit("flow-ui-lazy-load");
      } else {
        this.animateExpand();
      }
    } else {
      this.animateCollapse();
    }
  }
  handleLazyChange() {
    this.emit("flow-ui-lazy-change");
  }
  /** Gets all the nested tree items in this node. */
  getChildrenItems({ includeDisabled = true } = {}) {
    return this.childrenSlot ? [...this.childrenSlot.assignedElements({ flatten: true })].filter(
      (item) => _FlowUiTreeItem.isTreeItem(item) && (includeDisabled || !item.disabled)
    ) : [];
  }
  render() {
    const isRtl = this.localize.dir() === "rtl";
    const showExpandButton = !this.loading && (!this.isLeaf || this.lazy);
    return html`
      <div
        part="base"
        class="${classMap({
      "tree-item": true,
      "tree-item--expanded": this.expanded,
      "tree-item--selected": this.selected,
      "tree-item--disabled": this.disabled,
      "tree-item--hidden": this.hidden,
      "tree-item--small": this.size === "small",
      "tree-item--medium": this.size === "medium",
      "tree-item--large": this.size === "large",
      "tree-item--leaf": this.isLeaf,
      "tree-item--has-expand-button": showExpandButton,
      "tree-item--rtl": this.localize.dir() === "rtl"
    })}"
      >
        <div
          class="tree-item__item"
          part="
            item
            ${this.disabled ? "item--disabled" : ""}
            ${this.expanded ? "item--expanded" : ""}
            ${this.indeterminate ? "item--indeterminate" : ""}
            ${this.selected ? "item--selected" : ""}
          "
        >
          <div class="tree-item__indentation" part="indentation"></div>

          <div
            part="expand-button"
            class=${classMap({
      "tree-item__expand-button": true,
      "tree-item__expand-button--visible": showExpandButton
    })}
            aria-hidden="true"
          >
            ${when(
      this.loading,
      () => html`
                <flow-ui-progress-ring
                  size=${this.size === "large" ? "medium" : this.size}
                  indeterminate
                ></flow-ui-progress-ring>
              `
    )}
            <slot class="tree-item__expand-icon-slot" name="expand-icon">
              <flow-ui-icon library="system" name=${isRtl ? "chevron-left" : "chevron-right"}></flow-ui-icon>
            </slot>
            <slot class="tree-item__expand-icon-slot" name="collapse-icon">
              <flow-ui-icon library="system" name=${isRtl ? "chevron-left" : "chevron-right"}></flow-ui-icon>
            </slot>
          </div>

          ${when(
      this.selectable,
      () => html`
              <flow-ui-checkbox
                part="checkbox"
                exportparts="
                    base:checkbox__base,
                    control:checkbox__control,
                    control--checked:checkbox__control--checked,
                    control--indeterminate:checkbox__control--indeterminate,
                    checked-icon:checkbox__checked-icon,
                    indeterminate-icon:checkbox__indeterminate-icon,
                    label:checkbox__label
                  "
                class="tree-item__checkbox"
                ?disabled="${this.disabled}"
                ?checked="${live(this.selected)}"
                ?indeterminate="${this.indeterminate}"
                tabindex="-1"
                size="${this.size}"
              ></flow-ui-checkbox>
            `
    )}

          <slot class="tree-item__label" part="label"></slot>
        </div>

        <slot
          name="children"
          class="tree-item__children"
          part="children"
          role="group"
          @slotchange="${this.handleChildrenSlotChange}"
        ></slot>
      </div>
    `;
  }
};
_FlowUiTreeItem.styles = styles;
__decorateClass([
  state()
], _FlowUiTreeItem.prototype, "indeterminate", 2);
__decorateClass([
  state()
], _FlowUiTreeItem.prototype, "isLeaf", 2);
__decorateClass([
  state()
], _FlowUiTreeItem.prototype, "loading", 2);
__decorateClass([
  state()
], _FlowUiTreeItem.prototype, "selectable", 2);
__decorateClass([
  property({ reflect: true })
], _FlowUiTreeItem.prototype, "value", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], _FlowUiTreeItem.prototype, "expanded", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], _FlowUiTreeItem.prototype, "selected", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], _FlowUiTreeItem.prototype, "disabled", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], _FlowUiTreeItem.prototype, "lazy", 2);
__decorateClass([
  property({ reflect: true })
], _FlowUiTreeItem.prototype, "size", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], _FlowUiTreeItem.prototype, "hidden", 2);
__decorateClass([
  query("slot:not([name])")
], _FlowUiTreeItem.prototype, "defaultSlot", 2);
__decorateClass([
  query("slot[name=children]")
], _FlowUiTreeItem.prototype, "childrenSlot", 2);
__decorateClass([
  query(".tree-item__item")
], _FlowUiTreeItem.prototype, "itemElement", 2);
__decorateClass([
  query(".tree-item__children")
], _FlowUiTreeItem.prototype, "childrenContainer", 2);
__decorateClass([
  query(".tree-item__expand-button slot")
], _FlowUiTreeItem.prototype, "expandButtonSlot", 2);
__decorateClass([
  watch("value")
], _FlowUiTreeItem.prototype, "handleValueChange", 1);
__decorateClass([
  watch("loading", { waitUntilFirstUpdate: true })
], _FlowUiTreeItem.prototype, "handleLoadingChange", 1);
__decorateClass([
  watch("disabled")
], _FlowUiTreeItem.prototype, "handleDisabledChange", 1);
__decorateClass([
  watch("selected")
], _FlowUiTreeItem.prototype, "handleSelectedChange", 1);
__decorateClass([
  watch("expanded", { waitUntilFirstUpdate: true })
], _FlowUiTreeItem.prototype, "handleExpandedChange", 1);
__decorateClass([
  watch("expanded", { waitUntilFirstUpdate: true })
], _FlowUiTreeItem.prototype, "handleExpandAnimation", 1);
__decorateClass([
  watch("lazy", { waitUntilFirstUpdate: true })
], _FlowUiTreeItem.prototype, "handleLazyChange", 1);
let FlowUiTreeItem = _FlowUiTreeItem;
setDefaultAnimation("tree-item.expand", {
  keyframes: [
    { height: "0", opacity: "0", overflow: "hidden" },
    { height: "auto", opacity: "1", overflow: "hidden" }
  ],
  options: { duration: 250, easing: "cubic-bezier(0.4, 0.0, 0.2, 1)" }
});
setDefaultAnimation("tree-item.collapse", {
  keyframes: [
    { height: "auto", opacity: "1", overflow: "hidden" },
    { height: "0", opacity: "0", overflow: "hidden" }
  ],
  options: { duration: 200, easing: "cubic-bezier(0.4, 0.0, 0.2, 1)" }
});

export { FlowUiTreeItem as default };
