<template>
  <div class="my-1">
    <label class="col-form-label">{{ trans(ADDRESS_CITY) }}</label>
    <VueMultiselect
      id="citySelector"
      v-model="value"
      @search-change="listenInputSearch"
      ref="citySelector"
      @select="selectCity"
      @remove="remove"
      name="field"
      track-by="id"
      label="value"
      :custom-label="transName"
      :placeholder="trans(ADDRESS_SELECT_CITY)"
      :select-label="trans(MULTISELECT_SELECT_LABEL)"
      :deselect-label="trans(ADDRESS_CREATE_POSTAL_CODE)"
      :selected-label="trans(MULTISELECT_SELECTED_LABEL)"
      :taggable="true"
      :multiple="false"
      :internal-search="false"
      @tag="addPostcode"
      :tag-placeholder="trans(ADDRESS_CREATE_POSTAL_CODE)"
      :loading="isLoading"
      :options="cities"
    />
  </div>

  <div
    class="custom-postcode row g-1"
    v-if="writeNewPostcode || (isEnteredCustomCity && !isCitySelectorOpen)"
  >
    <div class="col-4">
      <div class="form-floating">
        <input
          class="form-control"
          type="text"
          id="code"
          :placeholder="trans(ADDRESS_POSTAL_CODE_CODE)"
          v-model="code"
        />
        <label for="code">{{ trans(ADDRESS_POSTAL_CODE_CODE) }}</label>
      </div>
    </div>
    <div class="col-8">
      <div class="form-floating">
        <input
          class="form-control"
          type="text"
          id="name"
          :placeholder="trans(ADDRESS_POSTAL_CODE_NAME)"
          v-model="name"
        />
        <label for="name">{{ trans(ADDRESS_POSTAL_CODE_NAME) }}</label>
      </div>
    </div>
  </div>
</template>

<script>
import VueMultiselect from "vue-multiselect";
import { searchCities, fetchCities } from "../../api.js";
import {
  MULTISELECT_SELECTED_LABEL,
  MULTISELECT_SELECT_LABEL,
  ADDRESS_POSTAL_CODE_CODE,
  ADDRESS_POSTAL_CODE_NAME,
  ADDRESS_CREATE_POSTAL_CODE,
  ADDRESS_CITY,
  ADDRESS_SELECT_CITY,
  trans,
} from "translator";

export default {
  name: "CitySelection",
  components: { VueMultiselect },
  setup() {
    return {
      MULTISELECT_SELECTED_LABEL,
      MULTISELECT_SELECT_LABEL,
      ADDRESS_CITY,
      ADDRESS_SELECT_CITY,
      ADDRESS_POSTAL_CODE_CODE,
      ADDRESS_POSTAL_CODE_NAME,
      ADDRESS_CREATE_POSTAL_CODE,
      trans,
    };
  },
  props: [
    "entity",
    "context",
    "focusOnAddress",
    "updateMapCenter",
    "flag",
    "checkErrors",
  ],
  emits: ["getReferenceAddresses"],
  data() {
    return {
      value: this.context.edit ? this.entity.address.postcode : null,
      isLoading: false,
    };
  },
  computed: {
    writeNewPostcode() {
      return this.entity.selected.writeNew.postcode;
    },
    isCitySelectorOpen() {
      return this.$refs.citySelector.$data.isOpen;
    },
    isEnteredCustomCity() {
      return (
        this.$data.value !== null &&
        typeof this.$data.value.text !== "undefined"
      );
    },
    cities() {
      return this.entity.loaded.cities.sort(
        (a, b) => Number(a.code) - Number(b.code) || a.name > b.name,
      );
    },
    name: {
      set(value) {
        this.entity.selected.postcode.name = value;
      },
      get() {
        return this.entity.selected.postcode.name;
      },
    },
    code: {
      set(value) {
        this.entity.selected.postcode.code = value;
      },
      get() {
        return this.entity.selected.postcode.code;
      },
    },
  },
  mounted() {
    console.log(
      "writeNew.postcode",
      this.entity.selected.writeNew.postcode,
      "in mounted",
    );
    if (this.context.edit) {
      this.entity.selected.city = this.value;
      this.entity.selected.postcode.name = this.value.name;
      this.entity.selected.postcode.code = this.value.code;
      this.$emit("getReferenceAddresses", this.value);
      if (typeof this.value.center !== "undefined") {
        this.updateMapCenter(this.value.center);
        if (this.value.center.coordinates) {
          this.entity.selected.postcode.coordinates =
            this.value.center.coordinates;
        }
      }
    }
  },
  methods: {
    transName(value) {
      return value.code && value.name ? `${value.name} (${value.code})` : "";
    },
    selectCity(value) {
      console.log(value);
      this.entity.selected.city = value;
      this.entity.selected.postcode.name = value.name;
      this.entity.selected.postcode.code = value.code;
      if (value.center) {
        this.entity.selected.postcode.coordinates = value.center.coordinates;
      }
      this.entity.selected.writeNew.postcode = false;
      this.$emit("getReferenceAddresses", value);
      this.focusOnAddress();
      if (value.center) {
        this.updateMapCenter(value.center);
      }
      this.checkErrors();
    },
    remove() {
      this.entity.selected.city = {};
      this.checkErrors();
    },
    listenInputSearch(query) {
      if (query.length > 2) {
        this.isLoading = true;
        searchCities(query, this.entity.selected.country)
          .then(
            (cities) =>
              new Promise((resolve) => {
                this.entity.loaded.cities = cities.results.filter(
                  (c) => c.origin !== 3,
                ); // filter out user-defined cities
                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;
          fetchCities(this.entity.selected.country)
            .then(
              (cities) =>
                new Promise((resolve) => {
                  this.entity.loaded.cities = cities.results.filter(
                    (c) => c.origin !== 3,
                  ); // filter out user-defined cities
                  this.isLoading = false;
                  resolve();
                }),
            )
            .catch((error) => {
              console.log(error);
              this.isLoading = false;
            });
        }
      }
      if (this.isCitySelectorOpen) {
        this.$data.value = { text: query };
      } else if (this.isEnteredCustomCity) {
        let city = this.splitCity(this.$data.value.text);
        this.$refs.citySelector.currentOptionLabel = "";
        this.entity.selected.city = city;
        this.entity.selected.postcode.name = city.name;
        this.entity.selected.postcode.code = city.code;
        this.entity.selected.writeNew.postcode = true;
        console.log("writeNew.postcode true, in listenInputSearch");
      }
    },
    splitCity(city) {
      let substr = city.split("-").map((s) => s.trim());
      if (substr.length === 1) {
        substr = city.split(" ");
      }
      //console.log('substr', substr);
      let decimal = [];
      substr.forEach((s, i) => {
        decimal[i] = /^\d+$/.test(s);
      });
      if (decimal[0] === true) {
        return {
          code: substr.shift(),
          name: substr.join(" "),
        };
      } else if (decimal[decimal.length - 1] === true) {
        return {
          code: substr.pop(),
          name: substr.join(" "),
        };
      }
      return {
        code: "",
        name: substr.join(" "),
      };
    },
    addPostcode() {
      console.log("addPostcode: pass here ?? never, it seems");
      this.entity.selected.writeNew.postcode = true;
      console.log("writeNew.postcode true, in addPostcode");
    },
  },
};
</script>

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