<script>

</script>

<script setup>
import { computed, ref, toRef } from "vue";
import { defu } from "defu";
import { DropdownMenu } from "reka-ui/namespaced";
import { DropdownMenuArrow } from "reka-ui";
import { reactiveOmit, createReusableTemplate } from "@vueuse/core";
import { FieldGroupReset } from "../composables/useFieldGroup";
import { useFilter } from "../composables/useFilter";
import { useLocale } from "../composables/useLocale";
import { usePortal } from "../composables/usePortal";
import { omit, get, isArrayOfArray } from "../utils";
import { pickLinkProps } from "../utils/link";
import { useComponentProps } from "../composables/useComponentProps";
import { useForwardProps } from "../composables/useForwardProps";
import icons from "../dictionary/icons";
import B24LinkBase from "./LinkBase.vue";
import B24Link from "./Link.vue";
import B24Avatar from "./Avatar.vue";
import B24Input from "./Input.vue";
import B24Kbd from "./Kbd.vue";
import B24DropdownMenuContent from "./DropdownMenuContent.vue";
defineOptions({ inheritAttrs: false });
const _props = defineProps({
  items: { type: null, required: false },
  arrow: { type: [Boolean, Object], required: false },
  portal: { type: [Boolean, String], required: false, skipCheck: true },
  sub: { type: Boolean, required: false },
  labelKey: { type: null, required: true },
  descriptionKey: { type: null, required: true },
  checkedIcon: { type: [Function, Object], required: false },
  externalIcon: { type: [Boolean, Function, Object], required: false },
  filter: { type: [Boolean, Object], required: false },
  filterFields: { type: Array, required: false },
  ignoreFilter: { type: Boolean, required: false },
  searchTerm: { type: String, required: false },
  class: { type: null, required: false },
  b24ui: { type: null, required: true },
  b24uiOverride: { type: null, required: false },
  loop: { type: Boolean, required: false },
  side: { type: null, required: false },
  sideOffset: { type: Number, required: false },
  sideFlip: { type: Boolean, required: false },
  align: { type: null, required: false },
  alignOffset: { type: Number, required: false },
  alignFlip: { type: Boolean, required: false },
  avoidCollisions: { type: Boolean, required: false },
  collisionBoundary: { type: null, required: false },
  collisionPadding: { type: [Number, Object], required: false },
  arrowPadding: { type: Number, required: false },
  hideShiftedArrow: { type: Boolean, required: false },
  sticky: { type: String, required: false },
  hideWhenDetached: { type: Boolean, required: false },
  positionStrategy: { type: String, required: false },
  updatePositionStrategy: { type: String, required: false },
  disableUpdateOnLayoutShift: { type: Boolean, required: false },
  prioritizePosition: { type: Boolean, required: false },
  reference: { type: null, required: false }
});
const emits = defineEmits(["update:searchTerm", "escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "closeAutoFocus"]);
const slots = defineSlots();
const props = useComponentProps("dropdownMenu", _props);
const { t, dir } = useLocale();
const { filterGroups } = useFilter();
const _searchTerm = ref("");
const searchTerm = computed({
  get: () => props.searchTerm ?? _searchTerm.value,
  set: (value) => {
    _searchTerm.value = value;
    emits("update:searchTerm", value);
  }
});
const inputProps = toRef(() => defu(props.filter, { placeholder: t("dropdownMenu.search"), variant: "none" }));
const portalProps = usePortal(toRef(() => props.portal));
const contentProps = useForwardProps(reactiveOmit(props, "sub", "items", "portal", "labelKey", "descriptionKey", "checkedIcon", "externalIcon", "filter", "filterFields", "ignoreFilter", "searchTerm", "class", "b24ui", "b24uiOverride"), emits);
const getProxySlots = () => omit(slots, ["default"]);
const arrowProps = toRef(() => defu(typeof props.arrow === "boolean" ? {} : props.arrow, { width: 20, height: 10 }));
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate();
const childrenIcon = computed(() => dir.value === "rtl" ? icons.chevronLeft : icons.chevronRight);
const groups = computed(() => {
  if (!props.items?.length) return [];
  return isArrayOfArray(props.items) ? props.items : [props.items];
});
const isStructuralItem = (item) => !!item.type && ["label", "separator"].includes(item.type);
const filteredGroups = computed(() => {
  if (!props.filter || props.ignoreFilter || !searchTerm.value) {
    return groups.value;
  }
  const fields = Array.isArray(props.filterFields) && props.filterFields.length ? props.filterFields : [props.labelKey];
  return filterGroups(groups.value, searchTerm.value, {
    fields,
    isStructural: isStructuralItem
  });
});
const hasFilteredItems = computed(() => filteredGroups.value.some((group) => group.some((item) => !isStructuralItem(item))));
</script>

<template>
  <DefineItemTemplate v-slot="{ item, active, index }">
    <slot
      :name="item.slot || 'item'"
      :item="item"
      :index="index"
      :b24ui="props.b24ui"
    >
      <slot
        :name="item.slot ? `${item.slot}-leading` : 'item-leading'"
        :item="item"
        :active="active"
        :index="index"
        :b24ui="props.b24ui"
      >
        <B24Avatar
          v-if="item.avatar"
          :size="item.b24ui?.itemLeadingAvatarSize || props.b24uiOverride?.itemLeadingAvatarSize || props.b24ui.itemLeadingAvatarSize()"
          v-bind="item.avatar"
          data-slot="itemLeadingAvatar"
          :class="props.b24ui.itemLeadingAvatar({ class: [props.b24uiOverride?.itemLeadingAvatar, item.b24ui?.itemLeadingAvatar], active })"
        />
      </slot>

      <span
        v-if="get(item, props.labelKey) || !!slots[item.slot ? `${item.slot}-label` : 'item-label'] || (get(item, props.descriptionKey) || !!slots[item.slot ? `${item.slot}-description` : 'item-description'])"
        data-slot="itemWrapper"
        :class="props.b24ui.itemWrapper({ class: [props.b24uiOverride?.itemWrapper, item.b24ui?.itemWrapper] })"
      >
        <span data-slot="itemLabel" :class="props.b24ui.itemLabel({ class: [props.b24uiOverride?.itemLabel, item.b24ui?.itemLabel], active })">
          <slot :name="item.slot ? `${item.slot}-label` : 'item-label'" :item="item" :active="active" :index="index">
            {{ get(item, props.labelKey) }}
          </slot>
        </span>

        <span
          v-if="get(item, props.descriptionKey) || !!slots[item.slot ? `${item.slot}-description` : 'item-description']"
          data-slot="itemDescription"
          :class="props.b24ui.itemDescription({ class: [props.b24uiOverride?.itemDescription, item.b24ui?.itemDescription] })"
        >
          <slot
            :name="item.slot ? `${item.slot}-description` : 'item-description'"
            :item="item"
            :active="active"
            :index="index"
          >
            {{ get(item, props.descriptionKey) }}
          </slot>
        </span>
      </span>

      <span data-slot="itemTrailing" :class="props.b24ui.itemTrailing({ class: [props.b24uiOverride?.itemTrailing, item.b24ui?.itemTrailing] })">
        <DropdownMenu.ItemIndicator as-child>
          <Component
            :is="props.checkedIcon || icons.check"
            data-slot="itemTrailingIcon"
            :class="props.b24ui.itemTrailingIcon({ class: [props.b24uiOverride?.itemTrailingIcon, item.b24ui?.itemTrailingIcon], color: item?.color })"
          />
        </DropdownMenu.ItemIndicator>

        <slot
          :name="item.slot ? `${item.slot}-trailing` : 'item-trailing'"
          :item="item"
          :active="active"
          :index="index"
          :b24ui="props.b24ui"
        >
          <Component
            :is="icons.loading"
            v-if="item.loading"
            data-slot="itemLeadingIcon"
            :class="props.b24ui.itemLeadingIcon({ class: [props.b24uiOverride?.itemLeadingIcon, item.b24ui?.itemLeadingIcon], color: item?.color, loading: true })"
          />
          <Component
            :is="childrenIcon"
            v-else-if="item.children?.length"
            data-slot="itemTrailingIcon"
            :class="props.b24ui.itemTrailingIcon({ class: [props.b24uiOverride?.itemTrailingIcon, item.b24ui?.itemTrailingIcon], color: item?.color, active })"
          />
          <Component
            :is="typeof props.externalIcon !== 'boolean' ? props.externalIcon : icons.external"
            v-else-if="item.target === '_blank' && props.externalIcon !== false"
            data-slot="itemLabelExternalIcon"
            :class="props.b24ui.itemLabelExternalIcon({ class: [props.b24uiOverride?.itemLabelExternalIcon, item.b24ui?.itemLabelExternalIcon], color: item?.color, active })"
          />
          <Component
            :is="item.icon"
            v-else-if="item.icon"
            data-slot="itemLeadingIcon"
            :class="props.b24ui.itemLeadingIcon({ class: [props.b24uiOverride?.itemLeadingIcon, item.b24ui?.itemLeadingIcon], color: item?.color, active })"
          />
          <span v-else-if="item.kbds?.length" data-slot="itemTrailingKbds" :class="props.b24ui.itemTrailingKbds({ class: [props.b24uiOverride?.itemTrailingKbds, item.b24ui?.itemTrailingKbds] })">
            <B24Kbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="item.b24ui?.itemTrailingKbdsSize || props.b24uiOverride?.itemTrailingKbdsSize || props.b24ui.itemTrailingKbdsSize()" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
          </span>
        </slot>
      </span>
    </slot>
  </DefineItemTemplate>

  <DropdownMenu.Portal v-bind="portalProps">
    <FieldGroupReset>
      <component
        :is="props.sub ? DropdownMenu.SubContent : DropdownMenu.Content"
        data-slot="content"
        :class="props.b24ui.content({ class: [props.b24uiOverride?.content, props.class] })"
        v-bind="contentProps"
      >
        <DropdownMenu.Filter v-if="!!props.filter" v-model="searchTerm" as-child>
          <B24Input
            no-border
            autofocus
            autocomplete="off"
            size="md"
            v-bind="inputProps"
            data-slot="input"
            :class="props.b24ui.input({ class: props.b24uiOverride?.input })"
            @change.stop
          />
        </DropdownMenu.Filter>

        <slot name="content-top" :sub="props.sub ?? false" />

        <div v-if="!searchTerm || hasFilteredItems" role="presentation" data-slot="viewport" :class="props.b24ui.viewport({ class: props.b24uiOverride?.viewport })">
          <DropdownMenu.Group
            v-for="(group, groupIndex) in filteredGroups"
            :key="`group-${groupIndex}`"
            data-slot="group"
            :class="props.b24ui.group({ class: props.b24uiOverride?.group })"
          >
            <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
              <DropdownMenu.Label v-if="item.type === 'label'" data-slot="label" :class="props.b24ui.label({ class: [props.b24uiOverride?.label, item.b24ui?.label, item.class] })">
                <ReuseItemTemplate :item="item" :index="index" />
              </DropdownMenu.Label>
              <DropdownMenu.Separator v-else-if="item.type === 'separator'" data-slot="separator" :class="props.b24ui.separator({ class: [props.b24uiOverride?.separator, item.b24ui?.separator, item.class] })" />
              <DropdownMenu.Sub
                v-else-if="item?.children?.length"
                :open="item.open"
                :default-open="item.defaultOpen"
              >
                <DropdownMenu.SubTrigger
                  as="button"
                  type="button"
                  :disabled="item.disabled"
                  :text-value="get(item, props.labelKey)"
                  data-slot="item"
                  :class="props.b24ui.item({ class: [props.b24uiOverride?.item, item.b24ui?.item, item.class], color: item?.color })"
                >
                  <ReuseItemTemplate :item="item" :index="index" />
                </DropdownMenu.SubTrigger>

                <B24DropdownMenuContent
                  sub
                  data-slot="content"
                  :class="item.b24ui?.content"
                  :b24ui="props.b24ui"
                  :b24ui-override="props.b24uiOverride"
                  :portal="props.portal"
                  :items="item.children"
                  :arrow="props.arrow"
                  align="start"
                  :align-offset="-4"
                  :side-offset="3"
                  :label-key="props.labelKey"
                  :description-key="props.descriptionKey"
                  :checked-icon="props.checkedIcon"
                  :external-icon="props.externalIcon"
                  v-bind="item.content"
                  :filter="item.filter"
                  :filter-fields="item.filterFields || props.filterFields"
                  :ignore-filter="item.ignoreFilter ?? props.ignoreFilter"
                >
                  <template v-for="(_, name) in getProxySlots()" #[name]="slotData">
                    <slot :name="name" v-bind="slotData" />
                  </template>
                  <DropdownMenuArrow v-if="!!props.arrow" v-bind="arrowProps" data-slot="arrow" :class="props.b24ui.arrow({ class: props.b24ui?.arrow })" />
                </B24DropdownMenuContent>
              </DropdownMenu.Sub>
              <DropdownMenu.CheckboxItem
                v-else-if="item.type === 'checkbox'"
                :model-value="item.checked"
                :disabled="item.disabled"
                :text-value="get(item, props.labelKey)"
                data-slot="item"
                :class="props.b24ui.item({ class: [props.b24uiOverride?.item, item.b24ui?.item, item.class], color: item?.color })"
                @update:model-value="item.onUpdateChecked"
                @select="item.onSelect"
              >
                <ReuseItemTemplate :item="item" :index="index" />
              </DropdownMenu.CheckboxItem>
              <B24Link v-else v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
                <DropdownMenu.Item
                  as-child
                  :disabled="item.disabled"
                  :text-value="get(item, props.labelKey)"
                  @select="item.onSelect"
                >
                  <B24LinkBase
                    v-bind="slotProps"
                    data-slot="item"
                    :class="props.b24ui.item({ class: [props.b24uiOverride?.item, item.b24ui?.item, item.class], color: item?.color, active })"
                  >
                    <ReuseItemTemplate :item="item" :active="active" :index="index" />
                  </B24LinkBase>
                </DropdownMenu.Item>
              </B24Link>
            </template>
          </DropdownMenu.Group>
        </div>

        <div v-if="searchTerm && !hasFilteredItems" data-slot="empty" :class="props.b24ui.empty({ class: props.b24uiOverride?.empty })">
          <slot name="empty" :search-term="searchTerm">
            {{ t("dropdownMenu.noMatch", { searchTerm }) }}
          </slot>
        </div>

        <slot />

        <slot name="content-bottom" :sub="props.sub ?? false" />
      </component>
    </FieldGroupReset>
  </DropdownMenu.Portal>
</template>
