<template>
  <w-select
    v-bind="$props"
    ref="input"
    :model-value="modelValue"
    use-input
    fill-input
    hide-dropdown-icon
    :clearable="clearable"
    :options="searchOptions"
    :hide-selected="!multiple"
    :use-chips="multiple"
    @filter="getOptions"
    @update:model-value="onInput"
    @blur="hideDisplay = false"
  >
    <template v-if="hasFilter && !searching" #no-option>
      <q-item>
        <q-item-section class="text-grey">
          {{ filterLength >= filterMinimumLength ? noOptionsText : `Enter at least ${filterMinimumLength - filterLength} more characters...` }}
        </q-item-section>
      </q-item>
    </template>
    <template v-for="(_, slot) of $slots" #[slot]="scope">
      <slot :name="slot" v-bind="{...scope}" />
    </template>
    <template #selected-item="scope">
      <q-chip
        removable
        dense
        :tabindex="scope.tabindex"
        color="white"
        text-color="secondary"
        @remove="scope.removeAtIndex(scope.index)"
      >
        <q-avatar v-if="scope.opt.icon && showChipIcon" text-color="primary" :icon="scope.opt.icon" />
        <span v-if="showChipType && scope.opt.type" class="text-capitalize text-primary q-pr-xs">{{ scope.opt.type }}: </span>
        <span>{{ scope.opt.label }}</span>
      </q-chip>
    </template>
  </w-select>
</template>

<script>
import WSelect from "../select/WSelect";

export default {
  name: "WAutocomplete",
  mixins: [WSelect],
  inheritAttrs: true,
  props: {
    search: {
      type: Function,
      required: true,
    },
    noOptionsText: {
      type: String,
      default: "No results",
    },
    filterMinimumLength: {
      type: Number,
      default: 3,
    },
    showChipIcon: {
      type: Boolean,
      default: false
    },
    showChipType: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: "Enter at least 3 characters..."
    },
    clearable: {
      type: Boolean,
      default: true
    },
    modelValue: {
      type: [Object, String],
      default: null,
    }
  },
  emits: ["update:modelValue"],
  data() {
    return {
      searchOptions: [],
      hasFilter: false,
      filterLength: null,
      searching: false,
    };
  },
  methods: {
    getOptions(val, update, abort) {
      this.hasFilter = !!val;
      this.filterLength = this.hasFilter && val.length;

      if (val !== "" && val.length >= this.filterMinimumLength) {
        this.searching = true;
        this.search(val, (err, returnedOptions) => {
          this.searching = false;

          if (err) {
            abort();
          } else {
            update(() => {
              this.searchOptions = returnedOptions;
            });
          }
        });
      } else {
        update(() => {
          this.searchOptions = [];
        });
      }
    },
    onInput(option) {
      this.$emit("update:modelValue", option);
      this.$refs.input.blur();
    },
  }
};
</script>
