<template>
  <div>
    <v-autocomplete
      v-model="model"
      :loading="loading"
      :items="items"
      :search-input.sync="search"
      hide-no-data
      hide-details
      return-object
      auto-select-first
      clearable
      :label="$t('where') + ' ?'"
      outlined
      append-icon="mdi-crosshairs-gps"
      @change="$emit('change', $event ? $event.value : '')"
      @click:append="geolocalizeUser"
    />
    <v-snackbar :value="errorMsg !== ''">
      {{ errorMsg }}
      <template #action="{ attrs }">
        <v-btn text v-bind="attrs" @click="errorMsg=''">
          {{ $t('close') }}
        </v-btn>
      </template>
    </v-snackbar>
  </div>
</template>

<script lang="ts">

import Vue from 'vue'

/**
 * Address properties as returned by the https://geo.api.gouv.fr/adresse API
 */
interface AddressProperties {
  label: string,
  score: number,
  housenumber: string,
  id: string,
  name: string,
  postcode: string,
  citycode: string,
  x: number,
  y: number,
  city: string,
  district: string,
  context: string,
  type: 'housenumber' | 'street' | 'locality' | 'municipality'
  importance: number,
  street: string
}

/**
 * Localized addresses as returned by the https://geo.api.gouv.fr/adresse API
 */
interface Feature {
  type: 'Feature',
  geometry: { type: 'Point', coordinates: [ number, number ]},
  properties: AddressProperties
}

export default Vue.extend({
  props: {
    value: {
      type: String,
      required: false,
      default: ''
    },
    type: {
      type: String,
      required: false,
      default: 'housenumber',
      validator (value: string) {
        return ['housenumber', 'street', 'locality', 'municipality'].includes(value)
      }
    },
    limit: {
      type: Number,
      required: false,
      default: 5
    },
    autocomplete: {
      type: Boolean,
      required: false,
      default: true
    }
  },
  data () {
    return {
      model: null as Address | null,
      search: null,
      features: [] as Array<Feature>,
      loading: false,
      errorMsg: ''
    }
  },
  computed: {
    items (): Array<Address> {
      return this.features.map((f: Feature) => {
        return {
          text: f.properties.name + ' (' + f.properties.postcode + ')',
          value: { longitude: f.geometry.coordinates[0] as number, latitude: f.geometry.coordinates[1] as number },
          disabled: false
        }
      })
    }
  },
  watch: {
    search (val: string) {
      if (!val) {
        this.features = []
        return
      }

      this.loading = true

      // Lazily load input items
      const apiUrl = 'https://api-adresse.data.gouv.fr/search/' +
                     `?type=${this.type}` +
                     `&autocomplete=${this.autocomplete ? 1 : 0}` +
                     `&limit=${this.limit}` +
                     `&q=${val}`

      fetch(encodeURI(apiUrl))
        .then(res => res.json())
        .then(({ features }) => {
          this.features = features
        })
        .catch((err) => {
          // eslint-disable-next-line no-console
          console.error(err)
        })
        .finally(() => {
          this.loading = false
        })
    }
  },
  methods: {
    clear () {
      this.model = null
      this.search = null
      this.features = []
      this.loading = false
      this.errorMsg = ''
    },
    geolocalizeUser () {
      if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(
          (position: { coords: { longitude: number, latitude: number }}) => {
            this.model = {
              text: this.$t('my_position') as string,
              value: { longitude: position.coords.longitude, latitude: position.coords.latitude }
            }
          },
          () => {
            this.errorMsg = this.$t('geolocation_error') as string
          }
        )
      } else {
        this.errorMsg = this.$t('geolocation_not_supported') as string
      }
    }
  }
})
</script>

<style>
.v-input__control {
  height: 56px;
}
</style>
