<script setup lang="ts">
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/vue";
import { computed } from "vue";

interface DropdownSelectable {
  id: number | string;
  name: string;
  iconName?: string;
}

// https://stackoverflow.com/questions/64775876/vue-3-pass-reactive-object-to-component-with-two-way-binding
interface Props {
  modelValue: {
    id: string | number;
    name: string;
  };
  items: DropdownSelectable[];
}

const emit = defineEmits<{
  (e: "update:modelValue", data: object): void;
}>();

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => {
    return {
      id: -1,
      name: "",
    };
  },
  items: () => [],
});

const dropdownSelected = computed<DropdownSelectable>({
  get: () => props.modelValue,
  set: (val) => emit("update:modelValue", val),
});
</script>

<template>
  <Listbox v-model="dropdownSelected" as="div">
    <div class="mt-1 relative w-full">
      <ListboxButton
        class="bg-white relative w-full border pl-5 pr-10 py-3 text-left cursor-default font-bold flex flex-row items-center"
      >
        <span v-if="dropdownSelected.iconName" class="mr-4">
          <component :is="dropdownSelected.iconName"></component>
        </span>
        <span class="block truncate">{{ dropdownSelected.name }}</span>
        <span
          class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none"
        >
          <it-icon-arrow-down class="h-5 w-5" aria-hidden="true" />
        </span>
      </ListboxButton>

      <transition
        leave-active-class="transition ease-in duration-100"
        leave-from-class="opacity-100"
        leave-to-class="opacity-0"
      >
        <ListboxOptions
          class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
        >
          <ListboxOption
            v-for="item in items"
            :key="item.id"
            v-slot="{ active, selected }"
            as="template"
            :value="item"
          >
            <li
              :class="[
                active ? 'text-white bg-blue-900' : 'text-black',
                'cursor-default select-none relative py-2 pl-3 pr-9',
              ]"
              class="flex flex-row items-center"
            >
              <span v-if="item.iconName" class="mr-4">
                <component :is="item.iconName"></component>
              </span>
              <span
                :class="[
                  dropdownSelected ? 'font-semibold' : 'font-normal',
                  'block truncate',
                ]"
              >
                {{ item.name }}
              </span>

              <span
                v-if="dropdownSelected"
                class="text-blue-900 absolute inset-y-0 right-0 flex items-center pr-4"
              >
                <it-icon-check v-if="selected" class="h-5 w-5" aria-hidden="true" />
              </span>
            </li>
          </ListboxOption>
        </ListboxOptions>
      </transition>
    </div>
  </Listbox>
</template>
