import { html } from 'lit';
import { property } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { boolean } from '../../internal/boolean.mjs';
import FlowRdfElement from '../../internal/flow-ui-rdf-element.mjs';
import { watch } from '../../internal/watch.mjs';
import styles from './list.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;
};
class FlowUiList extends FlowRdfElement {
  constructor() {
    super();
    this.draggedItem = null;
    this.draggedOverItem = null;
    this.selectable = false;
    this.editable = false;
    this.reorder = false;
    this.removable = false;
  }
  connectedCallback() {
    super.connectedCallback();
    this.editable = boolean(this.editable, true);
    this.reorder = boolean(this.reorder, true);
    this.removable = boolean(this.removable, true);
    this.selectable = boolean(this.selectable, true);
  }
  disconnectedCallback() {
    super.disconnectedCallback();
  }
  get listItems() {
    return [...this.querySelectorAll("flow-ui-list-item")];
  }
  handleStyleChange() {
    this.syncItems();
  }
  handleValueChange() {
    if (this.hasUpdated) {
      this.updateCheckedItem();
    }
  }
  handleItemClick(event) {
    if (!this.selectable) {
      return;
    }
    const target = event.target.closest("flow-ui-list-item");
    const items = this.listItems;
    const oldValue = this.value;
    if (target.disabled) {
      return;
    }
    this.value = target.value;
    items.forEach((item) => item.checked = item === target);
    if (this.value !== oldValue) {
      this.emit("flow-ui-change");
      this.emit("flow-ui-input");
    }
  }
  handleKeyDown(event) {
    if (!this.selectable) {
      return;
    }
    if (!["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", " "].includes(event.key)) {
      return;
    }
    const items = this.listItems.filter((item) => !item.disabled);
    const checkedItem = items.find((item) => item.checked) ?? items[0];
    const incr = event.key === " " ? 0 : ["ArrowUp", "ArrowLeft"].includes(event.key) ? -1 : 1;
    const oldValue = this.value;
    let index = items.indexOf(checkedItem) + incr;
    if (index < 0) {
      index = items.length - 1;
    }
    if (index > items.length - 1) {
      index = 0;
    }
    this.listItems.forEach((item) => {
      item.checked = false;
      item.tabIndex = -1;
    });
    this.value = items[index].value;
    items[index].checked = true;
    items[index].tabIndex = 0;
    items[index].focus();
    if (this.value !== oldValue) {
      this.emit("flow-ui-change");
      this.emit("flow-ui-input");
    }
    event.preventDefault();
  }
  syncItems() {
    if (customElements.get("flow-ui-list-item")) {
      const items = this.listItems;
      items.forEach((item) => {
        item.checked = item.value === this.value;
        item.removable = this.removable;
        item.editable = this.editable;
        item.reorder = this.reorder;
        item.selectable = this.selectable;
      });
      if (!items.some((item) => item.checked)) {
        items[0].tabIndex = 0;
      }
    } else {
      customElements.whenDefined("flow-ui-list-item").then(() => this.syncItems());
    }
  }
  updateCheckedItem() {
    const items = this.listItems;
    items.forEach((item) => item.checked = item.value === this.value);
  }
  handleDragStart(ev) {
    this.draggedItem = ev.target;
  }
  handleDragOver(ev) {
    ev.stopPropagation();
    if (!this.draggedItem) {
      return;
    }
    let target = ev.target.closest("flow-ui-list-item");
    if (target === this.draggedItem) {
      target = null;
    }
    if (target && target !== this.draggedOverItem) {
      if (this.draggedItem === target.previousElementSibling) {
        this.insertBefore(this.draggedItem, target.nextSibling);
      } else if (this.draggedItem === target.nextElementSibling) {
        this.insertBefore(this.draggedItem, target);
      }
      this.draggedOverItem = null;
    } else {
      this.draggedOverItem = target;
    }
  }
  handleDrop(_ev) {
    if (!this.draggedItem || !this.draggedOverItem) {
      return;
    }
  }
  handleDragEnd(_ev) {
    this.draggedItem = null;
    this.draggedOverItem = null;
  }
  render() {
    const defaultSlot = html`
      <slot @click=${this.handleItemClick} @keydown=${this.handleKeyDown} @slotchange=${this.syncItems}></slot>
    `;
    return html`
      <div
        part="base"
        class=${classMap({
      list: true
    })}
        @flow-ui-drag-start=${this.handleDragStart}
        @flow-ui-drag-over=${this.handleDragOver}
        @flow-ui-drag-drop=${this.handleDrop}
        @flow-ui-drag-end=${this.handleDragEnd}
      >
        ${defaultSlot}
      </div>
    `;
  }
}
FlowUiList.styles = styles;
__decorateClass([
  property({ reflect: true })
], FlowUiList.prototype, "value", 2);
__decorateClass([
  property({ type: Boolean })
], FlowUiList.prototype, "selectable", 2);
__decorateClass([
  property({ type: Boolean })
], FlowUiList.prototype, "editable", 2);
__decorateClass([
  property({ type: Boolean })
], FlowUiList.prototype, "reorder", 2);
__decorateClass([
  property({ type: Boolean })
], FlowUiList.prototype, "removable", 2);
__decorateClass([
  watch(["reorder", "editable", "removable", "selectable"], { waitUntilFirstUpdate: true })
], FlowUiList.prototype, "handleStyleChange", 1);
__decorateClass([
  watch("value")
], FlowUiList.prototype, "handleValueChange", 1);

export { FlowUiList as default };
