<template>

   <button v-if="step1WithModal"
      @click="openShowPane"
      class="btn btn-create mt-4" type="button" name="button">
      {{ $t(getTextButton) }}
   </button>

   <teleport to="body" v-if="step1WithModal">
      <modal v-if="flag.showPane"
         modalDialogClass="modal-dialog-scrollable modal-xl"
         @close="flag.showPane = false">

         <template v-slot:header>
            <h2 class="modal-title">{{ $t(getTextTitle) }}
               <span v-if="flag.loading" class="loading">
                  <i class="fa fa-circle-o-notch fa-spin fa-fw"></i>
                  <span class="sr-only">Loading...</span>
               </span>
            </h2>
         </template>

         <template v-slot:body>
            <show-address
               v-bind:context="this.context"
               v-bind:options="this.options"
               v-bind:default="this.default"
               v-bind:entity="this.entity"
               v-bind:flag="this.flag">
            </show-address>
         </template>

         <template v-slot:footer>
            <button @click="openEditPane"
               class="btn btn-update">
               {{ $t('action.edit')}}
            </button>
            <button class="btn btn-save"
               @click.prevent="$emit('submitAddress', { getSubmited , flag })">
               {{ $t('action.save')}}
            </button>
         </template>

      </modal>
   </teleport>
   <div class="mt-4" v-else>

      <show-address v-if="flag.showPane"
         v-bind:context="this.context"
         v-bind:options="this.options"
         v-bind:default="this.default"
         v-bind:entity="this.entity"
         v-bind:flag="this.flag"
         v-bind:insideModal="false" @openEditPane="openEditPane"
         @submitAddress="$emit('submitAddress', { getSubmited , flag })">
      </show-address>
   </div>

   <teleport to="body" v-if="step2WithModal">
      <modal v-if="flag.editPane"
         modalDialogClass="modal-dialog-scrollable modal-xl"
         @close="flag.editPane = false">

         <template v-slot:header>
            <h2 class="modal-title">{{ $t(getTextTitle) }}
               <span v-if="flag.loading" class="loading">
                  <i class="fa fa-circle-o-notch fa-spin fa-fw"></i>
                  <span class="sr-only">Loading...</span>
               </span>
            </h2>
         </template>

         <template v-slot:body>
            <edit-address
               v-bind:context="this.context"
               v-bind:options="this.options"
               v-bind:default="this.default"
               v-bind:entity="this.entity"
               v-bind:flag="this.flag"
               @getCities="getCities"
               @getReferenceAddresses="getReferenceAddresses">
            </edit-address>
         </template>

         <template v-slot:footer>
            <button class="btn btn-cancel change-icon" @click="flag.showPane = true; flag.editPane = false;">
               {{ $t('action.cancel') }}
            </button>
            <button class="btn btn-update"
               @click="closeEditPane">
               {{ $t('action.valid')}}
            </button>
         </template>

      </modal>
   </teleport>
   <div class="mt-4" v-else>

      <edit-address v-if="flag.editPane"
         v-bind:context="this.context"
         v-bind:options="this.options"
         v-bind:default="this.default"
         v-bind:entity="this.entity"
         v-bind:flag="this.flag"
         v-bind:insideModal="false" @closeEditPane="closeEditPane"
         @getCities="getCities"
         @getReferenceAddresses="getReferenceAddresses">
      </edit-address>
   </div>

</template>

<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import ShowAddress from './ShowAddress.vue';
import EditAddress from './EditAddress.vue';
import {
   getAddress,
   fetchCountries, fetchCities, fetchReferenceAddresses,
   patchAddress, postAddress, postPostalCode, postAddressToPerson
} from '../api'

export default {
   name: "AddAddress",
   props: ['context', 'options'],
   emits: ['submitAddress'],
   components: {
      Modal,
      ShowAddress,
      EditAddress,
   },
   data() {
      return {
         flag: {
            showPane: false,
            editPane: false,
            loading: false,
            success: false
         },
         default: {
            textButton: { create: 'add_an_address_title', edit: 'edit_address' },
            title: { create: 'add_an_address_title', edit: 'edit_address' },
            bindModal: {
               step1: true,
               step2: true,
            },
         },
         entity: {
            address: {}, // <== loaded and returned
            loaded: {
               countries: [],
               cities: [],
               addresses: [],
            },
            selected: {  // <== make temporary changes
               isNoAddress: false,
               country: {},
               city: {},
               postcode: {
                  code: null,
                  name: null
               },
               address: {},
               writeNew: {
                  address: false,
                  postcode: false
               }
            },
            addressMap: {
               // Note: LeafletJs demands [lat, lon]
               // cfr https://macwright.com/lonlat/
               center : [48.8589, 2.3469],
               zoom: 12
            },
         },
         errorMsg: []
      }
   },
   computed: {

      // TODO improve: props options must override data default
      step1WithModal() {
         return (this.options.bindModal) ? this.options.bindModal.step1 : this.default.bindModal.step1;
      },
      step2WithModal() {
         return (this.options.bindModal) ? this.options.bindModal.step2 : this.default.bindModal.step2;
      },

      getTextButton() {
         if (this.options.textButton) {
            return (this.context.edit) ? this.options.textButton.edit : this.options.textButton.create;
         }
         return (this.context.edit) ? this.default.textButton.edit : this.default.textButton.create;
      },
      getTextTitle() {
         if (this.options.title) {
            return (this.context.edit) ? this.options.title.edit : this.options.title.create;
         }
         return (this.context.edit) ? this.default.title.edit : this.default.title.create;
      },

      getSubmited() {
         return this.entity.address;
      }
   },
   mounted() {
      if (!this.step1WithModal) {
         console.log('Mounted now !');
         this.openShowPane();
      }
   },
   methods: {

      /*
      *  Opening and closing Panes when interacting with buttons
      */
      openShowPane() {
         console.log('open the Show Panel');
         if (this.context.addressId) {
            this.getInitialAddress(this.context.addressId);
         }
         this.flag.showPane = true;
      },
      openEditPane() {
         console.log('open the Edit panel');
         this.initForm();
         this.getCountries();
      },
      closeEditPane() {
         console.log('close the Edit Panel (with validation)');
         this.applyChanges();
         this.flag.showPane = true;
         this.flag.editPane = false;
      },

      /*
      *  Async Fetch datas
      */
      getInitialAddress(id) {
         this.flag.loading = true;
         getAddress(id).then(
            address => new Promise((resolve, reject) => {
               this.entity.address = address;
               this.flag.loading = false;
               resolve();
         }))
         .catch((error) => {
            this.errorMsg.push(error.message);
            this.flag.loading = false;
         });
      },

      getCountries() {
         this.flag.loading = true;
         fetchCountries().then(
            countries => new Promise((resolve, reject) => {
               this.entity.loaded.countries = countries.results;
               this.flag.showPane = false;
               this.flag.editPane = true;
               this.flag.loading = false;
               resolve()
         }))
         .catch((error) => {
            this.errorMsg.push(error.message);
            this.flag.loading = false;
         });
      },

      getCities(country) {
         this.flag.loading = true;
         fetchCities(country).then(
            cities => new Promise((resolve, reject) => {
               this.entity.loaded.cities = cities.results.filter(c => c.origin !== 3); // filter out user-defined cities
               this.flag.loading = false;
               resolve();
         }))
         .catch((error) => {
            this.errorMsg.push(error.message);
            this.flag.loading = false;
         });
      },

      getReferenceAddresses(city) {
         this.flag.loading = true;
         fetchReferenceAddresses(city).then(
            addresses => new Promise((resolve, reject) => {
               this.entity.loaded.addresses = addresses.results;
               this.flag.loading = false;
               resolve();
         }))
         .catch((error) => {
            this.errorMsg.push(error.message);
            this.flag.loading = false;
         });
      },

      /*
      *   Make form ready for new changes
      */
      initForm() {
         console.log('init form');

         this.entity.loaded.addresses = [];
         this.entity.loaded.cities = [];
         this.entity.loaded.countries = [];

         this.entity.selected.isNoAddress = (this.context.edit && this.entity.address.text === '') ? true : false;

         this.entity.selected.country = this.context.edit ? this.entity.address.country : {};
         this.entity.selected.postcode = this.context.edit ? this.entity.address.postcode : {};
         this.entity.selected.city = {};

         this.entity.selected.address = {};
         this.entity.selected.address.street = this.context.edit ? this.entity.address.street: null;
         this.entity.selected.address.streetNumber = this.context.edit ? this.entity.address.streetNumber: null;
         this.entity.selected.address.floor = this.context.edit ? this.entity.address.floor: null;
         this.entity.selected.address.corridor = this.context.edit ? this.entity.address.corridor: null;
         this.entity.selected.address.steps = this.context.edit ? this.entity.address.steps: null;
         this.entity.selected.address.flat = this.context.edit ? this.entity.address.flat: null;
         this.entity.selected.address.buildingName = this.context.edit ? this.entity.address.buildingName: null;
         this.entity.selected.address.distribution = this.context.edit ? this.entity.address.distribution: null;
         this.entity.selected.address.extra = this.context.edit ? this.entity.address.extra: null;

         this.entity.selected.writeNew.address = this.context.edit;
         this.entity.selected.writeNew.postcode = this.context.edit;
      },

      /*
      *  When changes are validated,
      *  apply some transformations before asyncing with backend
      *  from entity.selected to entity.address
      */
      applyChanges() {

         let newAddress = {
            'isNoAddress': this.entity.selected.isNoAddress,
            'street': this.entity.selected.isNoAddress ? '' : this.entity.selected.address.street,
            'streetNumber': this.entity.selected.isNoAddress ? '' : this.entity.selected.address.streetNumber,
            'postcode': {'id': this.entity.selected.city.id },
            'floor': this.entity.selected.address.floor,
            'corridor': this.entity.selected.address.corridor,
            'steps': this.entity.selected.address.steps,
            'flat': this.entity.selected.address.flat,
            'buildingName': this.entity.selected.address.buildingName,
            'distribution': this.entity.selected.address.distribution,
            'extra': this.entity.selected.address.extra
         };

         if (this.entity.selected.address.point !== undefined) {
            newAddress = Object.assign(newAddress, {
               'point': this.entity.selected.address.point.coordinates
            });
         }
         if (this.entity.selected.writeNew.postcode) {
            let newPostcode = this.entity.selected.postcode;
            newPostcode = Object.assign(newPostcode, {
               'country': {'id': this.entity.selected.country.id },
            });
            newAddress = Object.assign(newAddress, {
               'newPostcode': newPostcode
            });
         }

         if (this.context.edit) {
            this.updateAddress({ addressId: this.context.addressId, newAddress: newAddress });
         } else {
            this.addAddress(newAddress);
         }
      },

      /*
      *  Async PATCH transactions,
      *  then update existing address with backend datas when promise is resolved
      */
      updateAddress(payload) {
         console.log('updateAddress payload', payload);

         // TODO change the condition because it writes new postal code in edit mode now: !writeNewPostalCode
         this.flag.loading = true;
         if ('newPostcode' in payload.newAddress) {
            let postcodeBody = payload.newAddress.newPostcode;
            postcodeBody = Object.assign(postcodeBody, {'origin': 3});

            postPostalCode(postcodeBody)
               .then(postalCode => {
                  let body = payload.newAddress;
                  body.postcode = {'id': postalCode.id },
                     patchAddress(payload.addressId, body)
                        .then(address => new Promise((resolve, reject) => {
                           console.log('update address');
                           this.entity.address = address;
                           this.flag.loading = false;
                           resolve();
                        }))
                        .catch((error) => {
                           this.errorMsg.push(error);
                           this.flag.loading = false;
                        });
               })

         } else {
            patchAddress(payload.addressId, payload.newAddress)
               .then(address => new Promise((resolve, reject) => {
                  console.log('update address');
                  this.entity.address = address;
                  this.flag.loading = false;
                  resolve();
               }))
               .catch((error) => {
                  this.errorMsg.push(error);
                  this.flag.loading = false;
               });
         }
      },

      /*
      *  Async POST transactions,
      *  creating new address, and receive backend datas when promise is resolved
      */
      addAddress(payload) {
         console.log('addAddress payload', payload);

         this.flag.loading = true;
         if('newPostcode' in payload){
            let postcodeBody = payload.newPostcode;
            postcodeBody = Object.assign(postcodeBody, {'origin': 3});

            postPostalCode(postcodeBody)
               .then(postalCode => {
                  let body = payload;
                  body.postcode = {'id': postalCode.id},
                     postAddress(body)
                        .then(address => new Promise((resolve, reject) => {
                           console.log('add address');
                           this.entity.address = address;
                           resolve();
                           this.flag.loading = false;
                        }))
                        .catch((error) => {
                           this.errorMsg.push(error);
                           this.flag.loading = false;
                        });
               })

         } else {
            postAddress(payload)
               .then(address => new Promise((resolve, reject) => {
                  console.log('add address');
                  this.entity.address = address;
                  resolve();
                  this.flag.loading = false;
               }))
               .catch((error) => {
                  this.errorMsg.push(error);
                  this.flag.loading = false;
               });
         }
      }


   }
}
</script>

<style lang="scss">
div.entity-address {
   position: relative;
   div.loading {
      position: absolute;
      right: 0; top: -55px;
   }
}
</style>
