import { createVNode as _createVNode, mergeProps as _mergeProps, resolveDirective as _resolveDirective } from "vue";
// Components
import { makeVTreeviewChildrenProps, VTreeviewChildren } from "./VTreeviewChildren.mjs";
import { makeVListProps, useListItems, VList } from "../../components/VList/VList.mjs"; // Composables
import { provideDefaults } from "../../composables/defaults.mjs";
import { makeFilterProps, useFilter } from "../../composables/filter.mjs";
import { useProxiedModel } from "../../composables/proxiedModel.mjs"; // Utilities
import { computed, provide, ref, toRaw, toRef } from 'vue';
import { genericComponent, omit, propsFactory, useRender } from "../../util/index.mjs"; // Types
import { VTreeviewSymbol } from "./shared.mjs";
function flatten(items) {
  let flat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  for (const item of items) {
    flat.push(item);
    if (item.children) flatten(item.children, flat);
  }
  return flat;
}
export const makeVTreeviewProps = propsFactory({
  openAll: Boolean,
  search: String,
  ...makeFilterProps({
    filterKeys: ['title']
  }),
  ...makeVTreeviewChildrenProps(),
  ...omit(makeVListProps({
    collapseIcon: '$treeviewCollapse',
    expandIcon: '$treeviewExpand',
    slim: true
  }), ['itemType', 'nav', 'openStrategy']),
  modelValue: {
    type: Array,
    default: () => []
  }
}, 'VTreeview');
export const VTreeview = genericComponent()({
  name: 'VTreeview',
  props: makeVTreeviewProps(),
  emits: {
    'update:opened': val => true,
    'update:activated': val => true,
    'update:selected': val => true,
    'update:modelValue': val => true,
    'click:open': value => true,
    'click:select': value => true
  },
  setup(props, _ref) {
    let {
      slots
    } = _ref;
    const {
      items
    } = useListItems(props);
    const activeColor = toRef(props, 'activeColor');
    const baseColor = toRef(props, 'baseColor');
    const color = toRef(props, 'color');
    const activated = useProxiedModel(props, 'activated');
    const model = useProxiedModel(props, 'modelValue');
    const _selected = useProxiedModel(props, 'selected', props.modelValue);
    const selected = computed({
      get: () => _selected.value,
      set(val) {
        _selected.value = val;
        model.value = val;
      }
    });
    const vListRef = ref();
    const opened = computed(() => props.openAll ? openAll(items.value) : props.opened);
    const flatItems = computed(() => flatten(items.value));
    const search = toRef(props, 'search');
    const {
      filteredItems
    } = useFilter(props, flatItems, search);
    const visibleIds = computed(() => {
      if (!search.value) return null;
      const getPath = vListRef.value?.getPath;
      if (!getPath) return null;
      return new Set(filteredItems.value.flatMap(item => {
        const itemVal = props.returnObject ? item.raw : item.props.value;
        return [...getPath(itemVal), ...getChildren(itemVal)].map(toRaw);
      }));
    });
    function getChildren(id) {
      const arr = [];
      const queue = (vListRef.value?.children.get(id) ?? []).slice();
      while (queue.length) {
        const child = queue.shift();
        if (!child) continue;
        arr.push(child);
        queue.push(...(vListRef.value?.children.get(child) ?? []).slice());
      }
      return arr;
    }
    function openAll(items) {
      let ids = [];
      for (const i of items) {
        if (!i.children) continue;
        ids.push(props.returnObject ? toRaw(i.raw) : i.value);
        if (i.children) {
          ids = ids.concat(openAll(i.children));
        }
      }
      return ids;
    }
    provide(VTreeviewSymbol, {
      visibleIds
    });
    provideDefaults({
      VTreeviewGroup: {
        activeColor,
        baseColor,
        color,
        collapseIcon: toRef(props, 'collapseIcon'),
        expandIcon: toRef(props, 'expandIcon')
      },
      VTreeviewItem: {
        activeClass: toRef(props, 'activeClass'),
        activeColor,
        baseColor,
        color,
        density: toRef(props, 'density'),
        disabled: toRef(props, 'disabled'),
        lines: toRef(props, 'lines'),
        variant: toRef(props, 'variant')
      }
    });
    useRender(() => {
      const listProps = VList.filterProps(props);
      const treeviewChildrenProps = VTreeviewChildren.filterProps(props);
      return _createVNode(VList, _mergeProps({
        "ref": vListRef
      }, listProps, {
        "class": ['v-treeview', props.class],
        "open-strategy": "multiple",
        "style": props.style,
        "opened": opened.value,
        "activated": activated.value,
        "onUpdate:activated": $event => activated.value = $event,
        "selected": selected.value,
        "onUpdate:selected": $event => selected.value = $event
      }), {
        default: () => [_createVNode(VTreeviewChildren, _mergeProps(treeviewChildrenProps, {
          "returnObject": props.returnObject,
          "items": items.value
        }), slots)]
      });
    });
    return {};
  }
});
//# sourceMappingURL=VTreeview.mjs.map