<template>
  <div>
    <div
      v-if="showDropDown && options.length > 0"
      class="fixed inset-0"
      @click="closeDropDown(false)"
      aria-hidden="true"
    ></div>
    <div class="flex items-center" v-if="label">
      <!-- label of select field -->
      <label class="block text-sm font-medium text-gray-900">
        {{ label }}
      </label>
      <!-- asterisk sign to render if field is required -->
      <p v-if="isRequired" class="ml-1 text-red-600">*</p>
    </div>
    <div class="relative mt-1">
      <div class="relative">
        <input
          type="text"
          class="relative w-full cursor-default rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 text-left shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 disabled:pointer-events-none disabled:opacity-50 sm:text-sm"
          aria-haspopup="listbox"
          aria-expanded="true"
          aria-labelledby="listbox-label"
          :value="inputValue"
          :placeholder="placeholder"
          autocomplete="off"
          @focus="openDropDown()"
          @input="onInput"
          :disabled="disabled"
          :id="id + '_input_search'"
        />
        <span
          class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
        >
          <svg
            class="h-5 w-5 animate-spin text-gray-400"
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            v-if="isSearching"
          >
            <circle
              class="opacity-25"
              cx="12"
              cy="12"
              r="10"
              stroke="currentColor"
              stroke-width="4"
            ></circle>
            <path
              class="opacity-75"
              fill="currentColor"
              d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
            ></path>
          </svg>
          <!-- Heroicon name: solid/selector -->
          <svg
            class="h-5 w-5 text-gray-400"
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 20 20"
            fill="currentColor"
            aria-hidden="true"
            v-if="!isSearching"
          >
            <path
              fill-rule="evenodd"
              d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"
              clip-rule="evenodd"
            />
          </svg>
        </span>
        <button
          class="absolute top-2.5 right-10 z-100"
          v-if="
            showCloseButton && (inputValue == null || inputValue.length == 0)
          "
          @click.stop="handleCrossClick"
          :id="id + '_button_close_dropdown'"
        >
          <c-icon
            name="close"
            type="outline-v2"
            class="h-4 w-4 text-gray-400"
            cursorType="cursor-pointer"
          />
        </button>
      </div>
      <!--
      Select popover, show/hide based on select state.

      Entering: ""
        From: ""
        To: ""
      Leaving: "transition ease-in duration-100"
        From: "opacity-100"
        To: "opacity-0"
    -->
      <div
        v-if="showDropDown"
        class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
      >
        <ul
          tabindex="-1"
          role="listbox"
          aria-labelledby="listbox-label"
          aria-activedescendant="listbox-option-3"
          v-if="options.length > 0"
        >
          <!--
          Select option, manage highlight styles based on mouseenter/mouseleave and keyboard navigation.
  
          Highlighted: "text-white bg-indigo-600", Not Highlighted: "text-gray-900"
        -->

          <span v-for="option in options" :key="option.id">
            <li
              class="relative cursor-default select-none bg-gray-100 px-3 py-2 text-left text-sm text-gray-700"
              role="option"
            >
              <span class="block truncate"> {{ option.label }} </span>
            </li>
            <li
              v-for="subOption in option.options"
              :class="[
                'group relative flex select-none justify-between gap-3 px-3 py-2 text-left text-gray-900',
                customiseCSS ? 'flex' : '',
                subOption.isDisabled
                  ? 'cursor-not-allowed opacity-50'
                  : 'cursor-default hover:bg-gray-100 hover:text-gray-900',
              ]"
              :key="subOption.id"
              role="option"
              @click="handleOptionClick(subOption)"
            >
              <!-- custom slot for option ui -->
              <slot
                v-if="$scopedSlots['custom-option']"
                name="custom-option"
                :subOption="subOption"
                :option="option"
                :keyField="keyField"
              ></slot>

              <!-- default option ui -->
              <template v-else>
                <div class="flex w-full items-center">
                  <img
                    v-if="subOption.image_url"
                    :src="subOption.image_url"
                    :class="[
                      'mr-3 h-10 w-10 flex-shrink-0 object-cover',
                      subOption.type === 'user' ? 'rounded-full' : 'rounded-md',
                    ]"
                    loading="lazy"
                    :alt="subOption.label"
                  />
                  <div
                    v-if="
                      !subOption.image_url &&
                      subOption.type === 'user' &&
                      subOption.initials
                    "
                    class="mr-3 flex h-10 w-10 items-center justify-center rounded-full bg-gray-500 text-white"
                  >
                    <span class="text-base text-white">{{
                      subOption.initials
                    }}</span>
                  </div>
                  <div
                    v-if="!subOption.image_url && subOption.icon"
                    class="mr-3 flex h-10 w-10 items-center justify-center rounded-md bg-gray-100"
                  >
                    <c-icon
                      :name="subOption.icon.name"
                      :type="subOption.icon.type"
                      :class="subOption.icon.class"
                      :viewBox="subOption.icon.viewBox"
                    ></c-icon>
                  </div>
                  <span class="flex-1">
                    <div class="flex items-center justify-between">
                      <span
                        class="flex"
                        :class="[
                          subOption[keyField] === value[keyField]
                            ? 'font-semibold'
                            : 'font-normal',
                          ' block break-words',
                        ]"
                      >
                        {{ subOption.label }}
                        <span
                          v-if="subOption.labelExtra"
                          class="ml-1 text-sm text-gray-400 group-hover:text-gray-400"
                          >{{ subOption.labelExtra }}</span
                        >
                        <div
                          v-if="
                            subOption.stock_level ||
                            (subOption.stock_level <= 0 &&
                              subOption.stock_level !== null)
                          "
                        >
                          <p
                            class="ml-2 text-sm"
                            :class="[quantityLabelColor(subOption)]"
                          >
                            {{ subOption.stock_level }} units
                          </p>
                        </div>
                      </span>
                      <slot name="custom-tag" :subOption="subOption"></slot>
                    </div>
                    <span
                      class="mt-1 text-sm font-normal text-gray-500 group-hover:text-gray-500"
                      v-if="subOption.description"
                    >
                      {{ subOption.description }}
                    </span>
                  </span>
                </div>
                <p
                  v-if="subOption.price"
                  class="relative flex items-center whitespace-nowrap text-sm text-gray-900"
                >
                  {{ subOption.price }}
                </p>
                <span
                  class="absolute inset-y-0 right-0 flex items-center pr-4 text-indigo-600 group-hover:text-white"
                  v-if="subOption[keyField] === value[keyField]"
                >
                  <svg
                    class="h-5 w-5"
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 20 20"
                    fill="currentColor"
                    aria-hidden="true"
                  >
                    <path
                      fill-rule="evenodd"
                      d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
                      clip-rule="evenodd"
                    />
                  </svg>
                </span>
              </template>
            </li>
          </span>

        </ul>
        <p v-else class="text-center">
          No match found. Try a different search.
        </p>
      </div>
    </div>
    <p v-if="isError" class="mt-2 text-left text-sm text-red-600">
      {{ errorMessage }}
    </p>
  </div>
</template>

<script>
import { debounce } from "lodash-es";
import CIcon from "../CIcon/CIcon.vue";

export default {
  name: "CGroupedSelect",
  components: {
    CIcon,
  },
  props: {
    label: String,
    options: Array,
    value: Object,
    placeholder: String,
    isSearching: Boolean,
    disabled: { type: Boolean, default: false },
    isError: { type: Boolean, default: false },
    errorMessage: {
      type: String,
      default: "This field cannot be empty",
    },
    keyField: { type: String, default: "label" },
    // whether the select field is mandatory or not
    isRequired: {
      type: Boolean,
    },
    customiseCSS: {
      type: Boolean,
      default: false,
    },
    showCloseButton: {
      type: Boolean,
      default: false,
    },
    // whether to search when the select field is focused
    searchOnFocus: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      showDropDown: false,
      inputValue: "",
    };
  },
  methods: {
    handleCrossClick(event) {
      event.preventDefault();
      this.$emit("hide-grouped-select-dropdown");
    },
    onInput(e) {
      this.inputValue = e.target.value;
      this.emitSearch(e.target.value);
    },
    emitSearch: debounce(function (value) {
      if (value !== this.value.label) {
        this.$emit("search", value);
      } else {
        this.$emit("search", "");
      }
    }, 500),
    handleOptionClick(option) {
      this.inputValue = option.label;
      this.closeDropDown(true);
      this.$emit("input", option);
    },
    closeDropDown(hasData) {
      this.inputValue = this.value.label;
      this.showDropDown = false;
      this.$emit("blur", { hasData: hasData });
    },
    openDropDown() {
      this.showDropDown = true;
      if (this.searchOnFocus) {
        this.emitSearch("");
      }
    },
    quantityLabelColor(data) {
      if (data.stock_level <= 0) {
        return "text-red-300";
      } else if (data.stock_level < data.alert_level) {
        return "text-orange-300";
      } else {
        return "text-gray-300";
      }
    },
  },
  watch: {
    value(newValue) {
      this.inputValue = newValue.label;
    },
  },
  mounted() {
    this.inputValue = this.value.label;
  },
};
</script>

<style scoped>
input::placeholder {
  @apply text-gray-500;
}
</style>
