<template>
  <Menu v-slot="{ open }" as="div" :class="ui.wrapper" @mouseleave="onMouseLeave">
    <MenuButton
      ref="trigger"
      as="div"
      :disabled="disabled"
      class="inline-flex w-full"
      role="button"
      @mouseover="onMouseOver"
    >
      <slot :open="open" :disabled="disabled">
        <button :disabled="disabled">
          Open
        </button>
      </slot>
    </MenuButton>

    <div v-if="open && items.length" ref="container" :class="[ui.container, ui.width]" :style="containerStyle" @mouseover="onMouseOver">
      <transition appear v-bind="ui.transition">
        <MenuItems :class="[ui.base, ui.divide, ui.ring, ui.rounded, ui.shadow, ui.background, ui.height]" static>
          <div v-for="(subItems, index) of items" :key="index" :class="ui.padding">
            <MenuItem v-for="(item, subIndex) of subItems" :key="subIndex" v-slot="{ active, disabled: itemDisabled }" :disabled="item.disabled">
              <ULinkCustom
                v-bind="omit(item, ['label', 'icon', 'iconClass', 'avatar', 'shortcuts', 'click'])"
                :class="[ui.item.base, ui.item.padding, ui.item.size, ui.item.rounded, active ? ui.item.active : ui.item.inactive, itemDisabled && ui.item.disabled]"
                @click="item.click"
              >
                <slot :name="item.slot || 'item'" :item="item">
                  <UIcon v-if="item.icon" :name="item.icon" :class="[ui.item.icon.base, active ? ui.item.icon.active : ui.item.icon.inactive, item.iconClass]" />
                  <UAvatar v-else-if="item.avatar" v-bind="{ size: ui.item.avatar.size, ...item.avatar }" :class="ui.item.avatar.base" />

                  <span class="truncate">{{ item.label }}</span>

                  <span v-if="item.shortcuts?.length" :class="ui.item.shortcuts">
                    <UKbd v-for="shortcut of item.shortcuts" :key="shortcut">{{ shortcut }}</UKbd>
                  </span>
                </slot>
              </ULinkCustom>
            </MenuItem>
          </div>
        </MenuItems>
      </transition>
    </div>
  </Menu>
</template>

<script>
import { Menu, MenuButton, MenuItems, MenuItem } from "@headlessui/vue";
import { defineComponent, ref, computed, onMounted } from "vue";
import { defu } from "defu";
import { omit } from "lodash-es";
import UIcon from "../elements/Icon.vue";
import UAvatar from "../elements/Avatar.vue";
import UKbd from "../elements/Kbd.vue";
import ULinkCustom from "../elements/LinkCustom.vue";
import { usePopper } from "../../composables/usePopper";
import { useAppConfig } from "#imports";
import appConfig from "#build/app.config";
export default defineComponent({
  components: {
    // eslint-disable-next-line vue/no-reserved-component-names
    Menu,
    MenuButton,
    MenuItems,
    MenuItem,
    UIcon,
    UAvatar,
    UKbd,
    ULinkCustom
  },
  props: {
    items: {
      type: Array,
      default: () => []
    },
    mode: {
      type: String,
      default: "click",
      validator: (value) => {
        return ["click", "hover"].includes(value);
      }
    },
    disabled: {
      type: Boolean,
      default: false
    },
    popper: {
      type: Object,
      default: () => ({})
    },
    openDelay: {
      type: Number,
      default: 50
    },
    closeDelay: {
      type: Number,
      default: 0
    },
    ui: {
      type: Object,
      default: () => appConfig.ui.dropdown
    }
  },
  setup(props) {
    const appConfig2 = useAppConfig();
    const ui = computed(() => defu({}, props.ui, appConfig2.ui.dropdown));
    const popper = computed(() => defu(props.mode === "hover" ? { offsetDistance: 0 } : {}, props.popper, ui.value.popper));
    const [trigger, container] = usePopper(popper.value);
    const menuApi = ref(null);
    let openTimeout = null;
    let closeTimeout = null;
    onMounted(() => {
      setTimeout(() => {
        const menuProvides = trigger.value?.$.provides;
        if (!menuProvides) {
          return;
        }
        const menuProvidesSymbols = Object.getOwnPropertySymbols(menuProvides);
        menuApi.value = menuProvidesSymbols.length && menuProvides[menuProvidesSymbols[0]];
      }, 200);
    });
    const containerStyle = computed(() => {
      const offsetDistance = props.popper?.offsetDistance || ui.value.popper?.offsetDistance || 8;
      return props.mode === "hover" ? { paddingTop: `${offsetDistance}px`, paddingBottom: `${offsetDistance}px` } : {};
    });
    function onMouseOver() {
      if (props.mode !== "hover" || !menuApi.value) {
        return;
      }
      if (closeTimeout) {
        clearTimeout(closeTimeout);
        closeTimeout = null;
      }
      if (menuApi.value.menuState === 0) {
        return;
      }
      openTimeout = openTimeout || setTimeout(() => {
        menuApi.value.openMenu && menuApi.value.openMenu();
        openTimeout = null;
      }, props.openDelay);
    }
    function onMouseLeave() {
      if (props.mode !== "hover" || !menuApi.value) {
        return;
      }
      if (openTimeout) {
        clearTimeout(openTimeout);
        openTimeout = null;
      }
      if (menuApi.value.menuState === 1) {
        return;
      }
      closeTimeout = closeTimeout || setTimeout(() => {
        menuApi.value.closeMenu && menuApi.value.closeMenu();
        closeTimeout = null;
      }, props.closeDelay);
    }
    return {
      // eslint-disable-next-line vue/no-dupe-keys
      ui,
      trigger,
      container,
      containerStyle,
      onMouseOver,
      onMouseLeave,
      omit
    };
  }
});
</script>
