<template>
  <div ref="placeSelect" class="relative-position">
    <q-select
      v-bind="$attrs"
      v-on="$listeners"
      v-model="place"
      @filter="filterFn"
      @focus="onFocus"
      map-options
      emit-value
      :options="options"
      :option-value="place => place"
      :option-label="place => getDisplayValue(place)"
      outlined
      use-input
      autocomplete="off"
      input-debounce="200"
      fill-input
      hide-selected
      label="Куда"
      popup-content-class="ui-place-select__result"
    >
      <template v-slot:option="option">
        <place-select-option
          v-bind="option.itemProps"
          v-on="option.itemEvents"
          :place="option.opt"
          :query="preparedQuery"
        />
      </template>
      <template slot="no-option">
        <place-select-empty-result
          v-if="query.length > 2"
          :country="country"
          :query="query"
        />
        <place-select-search-hint v-else :country="country" />
      </template>
    </q-select>
  </div>
</template>

<style></style>

<script lang="ts">
import { Component, Prop, Ref, Vue } from 'vue-property-decorator'
import PlaceSelectSearchHint from './PlaceSelectSearchHint.vue'
import PlaceSelectEmptyResult from './PlaceSelectEmptyResult.vue'
import PlaceSelectOption from './PlaceSelectOption.vue'
import Country from '../../dto/Country'
import Place from '../../dto/Place'
import DeliveryCalculatorStore, {
  getDeliveryCalculatorStore,
} from '../../utils/DeliveryCalculatorStore'
import LocationService from '../../utils/LocationService'
import { QSelect } from 'quasar'

@Component({
  inheritAttrs: false,
  components: {
    QSelect,
    PlaceSelectSearchHint,
    PlaceSelectEmptyResult,
    PlaceSelectOption,
  },
})
export default class PlaceSelect extends Vue {
  @Prop(Object) country!: Country
  @Ref('placeSelect') placeSelect!: HTMLInputElement

  query = ''
  calculatorStore!: DeliveryCalculatorStore
  options: readonly Place[] = Object.freeze([])

  created() {
    this.calculatorStore = getDeliveryCalculatorStore(this.$store)
  }

  get place(): Place | null {
    return this.calculatorStore.place
  }

  set place(place: Place | null) {
    if (place) {
      this.calculatorStore.setPlace(place)
    }
  }

  get preparedQuery(): string {
    return this.query.trim().toLowerCase()
  }

  getDisplayValue(place?: Place): string {
    return place
      ? [place.name, place.region].filter(value => !!value).join(', ')
      : ''
  }

  onFocus() {
    const input = this.placeSelect.querySelector(
      'input[type="search"]'
    ) as HTMLInputElement

    if (input) {
      input.select()
    }
  }

  filterFn(val: string, update: Function, abort: Function) {
    this.query = val.trim().toLowerCase()

    if (val.length < 1) {
      abort()
      return
    }

    if (val.length < 3) {
      update(() => (this.options = []))
      return
    }

    LocationService.searchPlaces(this.country.id, this.query).then(places =>
      update(() => (this.options = Object.freeze(places)))
    )
  }
}
</script>
