<template>
  <div class="my-1">
    <label class="col-form-label" for="addressSelector">{{
      trans(ADDRESS_ADDRESS)
    }}</label>
    <VueMultiselect
      id="addressSelector"
      v-model="value"
      :placeholder="trans(ADDRESS_SELECT_ADDRESS)"
      :tag-placeholder="trans(ADDRESS_CREATE_ADDRESS)"
      :select-label="trans(MULTISELECT_SELECT_LABEL)"
      :deselect-label="trans(ADDRESS_CREATE_ADDRESS)"
      :selected-label="trans(MULTISELECT_SELECTED_LABEL)"
      @search-change="listenInputSearch"
      :internal-search="false"
      ref="addressSelector"
      @select="selectAddress"
      @remove="remove"
      name="field"
      track-by="id"
      label="value"
      :custom-label="transName"
      :taggable="true"
      :multiple="false"
      @tag="addAddress"
      :loading="isLoading"
      :options="addresses"
    />
  </div>

  <div
    class="custom-address row g-1"
    v-if="
      writeNewAddress ||
      writeNewPostalCode ||
      (isEnteredCustomAddress && !isAddressSelectorOpen)
    "
  >
    <div class="col-10">
      <div class="form-floating">
        <input
          class="form-control"
          type="text"
          name="street"
          :placeholder="trans(ADDRESS_STREET)"
          v-model="street"
        />
        <label for="street">{{ trans(ADDRESS_STREET) }}</label>
      </div>
    </div>
    <div class="col-2">
      <div class="form-floating">
        <input
          class="form-control"
          type="text"
          name="streetNumber"
          :placeholder="trans(ADDRESS_STREET_NUMBER)"
          v-model="streetNumber"
        />
        <label for="streetNumber">{{ trans(ADDRESS_STREET_NUMBER) }}</label>
      </div>
    </div>
  </div>
</template>

<script>
import VueMultiselect from "vue-multiselect";
import {
  searchReferenceAddresses,
  fetchReferenceAddresses,
} from "../../api.js";
import {
  ADDRESS_STREET,
  ADDRESS_STREET_NUMBER,
  ADDRESS_ADDRESS,
  MULTISELECT_SELECTED_LABEL,
  MULTISELECT_SELECT_LABEL,
  ADDRESS_SELECT_ADDRESS,
  ADDRESS_CREATE_ADDRESS,
  trans,
} from "translator";

export default {
  name: "AddressSelection",
  components: { VueMultiselect },
  setup() {
    return {
      ADDRESS_STREET,
      ADDRESS_STREET_NUMBER,
      ADDRESS_ADDRESS,
      MULTISELECT_SELECTED_LABEL,
      MULTISELECT_SELECT_LABEL,
      ADDRESS_SELECT_ADDRESS,
      ADDRESS_CREATE_ADDRESS,
      trans,
    };
  },
  props: ["entity", "context", "updateMapCenter", "flag", "checkErrors"],
  data() {
    return {
      value: this.context.edit ? this.entity.address.addressReference : null,
      isLoading: false,
    };
  },
  computed: {
    writeNewAddress() {
      return this.entity.selected.writeNew.address;
    },
    writeNewPostalCode() {
      return this.entity.selected.writeNew.postCode;
    },
    isAddressSelectorOpen() {
      return this.$refs.addressSelector.$data.isOpen;
    },
    isEnteredCustomAddress() {
      return (
        this.$data.value !== null &&
        typeof this.$data.value.text !== "undefined"
      );
    },
    addresses() {
      return this.entity.loaded.addresses;
    },
    street: {
      set(value) {
        this.entity.selected.address.street = value;
      },
      get() {
        return this.entity.selected.address.street;
      },
    },
    streetNumber: {
      set(value) {
        this.entity.selected.address.streetNumber = value;
      },
      get() {
        return this.entity.selected.address.streetNumber;
      },
    },
  },
  methods: {
    transName(value) {
      return value.streetNumber === undefined
        ? value.street
        : `${value.streetNumber}, ${value.street}`;
    },
    selectAddress(value) {
      this.entity.selected.address = value;
      this.entity.selected.address.addressReference = {
        id: value.id,
      };
      this.entity.selected.address.street = value.street;
      this.entity.selected.address.streetNumber = value.streetNumber;
      this.entity.selected.writeNew.address = false;
      this.updateMapCenter(value.point);
      this.checkErrors();
    },
    remove() {
      this.entity.selected.address = {};
      this.checkErrors();
    },
    listenInputSearch(query) {
      //console.log('listenInputSearch', query, this.isAddressSelectorOpen);
      if (
        !this.entity.selected.writeNew.postcode &&
        "id" in this.entity.selected.city
      ) {
        if (query.length > 2) {
          this.isLoading = true;
          searchReferenceAddresses(query, this.entity.selected.city)
            .then(
              (addresses) =>
                new Promise((resolve) => {
                  this.entity.loaded.addresses = addresses.results;
                  this.isLoading = false;
                  resolve();
                }),
            )
            .catch((error) => {
              console.log(error); //TODO better error handling
              this.isLoading = false;
            });
        } else {
          if (query.length === 0) {
            // Fetch all cities when suppressing the query
            this.isLoading = true;
            fetchReferenceAddresses(this.entity.selected.city)
              .then(
                (addresses) =>
                  new Promise((resolve) => {
                    this.entity.loaded.addresses = addresses.results;
                    this.isLoading = false;
                    resolve();
                  }),
              )
              .catch((error) => {
                console.log(error);
                this.isLoading = false;
              });
          }
        }
      }

      if (this.isAddressSelectorOpen) {
        this.$data.value = { text: query };
      } else if (this.isEnteredCustomAddress) {
        let addr = this.splitAddress(this.$data.value.text);
        this.entity.selected.address.street = addr.street;
        this.entity.selected.address.streetNumber = addr.number;
        this.entity.selected.writeNew.address = true;
        this.checkErrors();
      }
    },
    splitAddress(address) {
      let substr = address.split(",").map((s) => s.trim());
      if (substr.length === 1) {
        substr = address.split(" ");
      }
      let decimal = [];
      substr.forEach((s, i) => {
        decimal[i] = /^\d+$/.test(s);
      });
      if (decimal[0] === true) {
        return {
          number: substr.shift(),
          street: substr.join(" "),
        };
      } else if (decimal[decimal.length - 1] === true) {
        return {
          number: substr.pop(),
          street: substr.join(" "),
        };
      }
      return {
        number: "",
        street: substr.join(" "),
      };
    },
    addAddress() {
      this.entity.selected.writeNew.address = true;
    },
  },
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.css"></style>
