<template>
  <div
    :id="`custom-dropdown${identifier}`"
    :class="[
      'ui search selection dropdown',
      { 'active visible': isOpen },
      { disabled },
    ]"
    @click="toggleDropdown"
  >
    <input
      v-if="search"
      v-model="input"
      @input="isOpen = true"
      v-on:keyup.enter="select(0)"
      v-on:keyup.esc="toggleDropdown(false)"
      class="search"
      autocomplete="off"
      tabindex="0"
      :placeholder="placehold"
      ref="input"
    />
    <div v-if="!input" class="default text">
      {{ selected }}
    </div>
    <i
      :class="['dropdown icon', { clear: clearable && selected }]"
      @click="clear"
    ></i>
    <div :class="['menu', { 'visible transition': isOpen }]">
      <div
        v-for="(option, index) in processedOptions || ['No results found.']"
        @click="select(index)"
        :key="option + index"
        :class="[
          processedOptions ? 'item' : 'message',
          { 'active selected': option.name === selected },
        ]"
      >
        <span v-if="option.name">
          {{ option.name }}
        </span>
        <span v-else>
          {{ option }}
        </span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Dropdown",

  props: [
    "options",
    "selected",
    "disabled",
    "search",
    "placeholder",
    "clearable",
  ],

  computed: {
    processedOptions: function () {
      let options = this.options;
      if (this.search && this.input !== "") {
        options = this.searchOptions(this.options);
      }
      return options.length > 0 ? options : null;
    },

    placehold() {
      return this.input ? "" : this.placeholder;
    },
  },

  data() {
    return {
      isOpen: false,
      input: "",
      identifier: 0,
    };
  },

  methods: {
    toggleDropdown(val) {
      if (this.isOpen) {
        this.input = ""; // * clear input field when closing dropdown
      } else if (this.search) {
        //* focus on input if is a search dropdown
        this.$refs.input.focus({
          preventScroll: true,
        });
      } else if (this.clearable && val.target && this.selected) {
        this.clear(); //* clear selected and input
      }
      this.isOpen = typeof val === "boolean" ? val : !this.isOpen;
    },

    select(index) {
      // * toggle dropdown is called several time, timeout delay this function to be the last
      setTimeout(() => {
        this.isOpen = false;
      }, 0);
      this.$emit("update:selection", this.processedOptions[index]);
      this.input = "";
    },

    searchOptions(options) {
      return options.filter((el) =>
        el.name
          ? el.name.toLowerCase().includes(this.input.toLowerCase())
          : el.toLowerCase().includes(this.input.toLowerCase())
      );
    },

    clear() {
      if (this.clearable) {
        this.input = "";
        this.$emit("update:selection", "");
        if (this.isOpen) this.toggleDropdown(false);
      }
    },

    clickOutsideDropdown(e) {
      if (!e.target.closest(`#custom-dropdown${this.identifier}`))
        this.toggleDropdown(false);
    },
  },

  created() {
    this.identifier = Math.floor(Math.random() * 10000);
    window.addEventListener("mousedown", this.clickOutsideDropdown);
  },

  beforeDestroy() {
    window.removeEventListener("mousedown", this.clickOutsideDropdown);
  },
};
</script>

<style scoped>
.ui.selection.dropdown .menu > .item {
  white-space: nowrap;
}
</style>