<script setup lang="ts">
import type { DropdownSelectable } from "@/types";
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/vue";
import { computed } from "vue"; // https://stackoverflow.com/questions/64775876/vue-3-pass-reactive-object-to-component-with-two-way-binding

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

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

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

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

<template>
  <Listbox v-model="dropdownSelected" as="div">
    <div class="relative w-full">
      <ListboxButton
        class="relative flex w-full cursor-default flex-row items-center bg-white py-3 pl-5 pr-10 text-left"
        :class="{
          border: !props.borderless,
          'font-bold': !props.borderless,
        }"
        data-cy="dropdown-select"
      >
        <span v-if="dropdownSelected.iconName" class="mr-4">
          <component :is="dropdownSelected.iconName"></component>
        </span>
        <span class="block truncate">
          {{ dropdownSelected.name }}
          <span v-if="placeholderText && !dropdownSelected.name" class="text-gray-900">
            {{ placeholderText }}
          </span>
        </span>
        <span
          class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
        >
          <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 max-h-60 w-full overflow-auto bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 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 ? 'bg-blue-900 text-white' : 'text-black',
                'relative cursor-default select-none py-2 pl-3 pr-9',
              ]"
              class="flex flex-row items-center"
              :data-cy="`dropdown-select-option-${item.name}`"
            >
              <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="absolute inset-y-0 right-0 flex items-center pr-4 text-blue-900"
              >
                <it-icon-check v-if="selected" class="h-5 w-5" aria-hidden="true" />
              </span>
            </li>
          </ListboxOption>
        </ListboxOptions>
      </transition>
    </div>
  </Listbox>
</template>
