<template>

   <!-- step0 -->
   <show-pane 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"
      @openEditPane="openEditPane"
      ref="showAddress">
   </show-pane>

   <!-- step 1 -->
   <teleport to="body" v-if="inModal">
      <modal v-if="flag.suggestPane"
         modalDialogClass="modal-dialog-scrollable modal-xl"
         @close="resetPane">

         <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">{{ $t('loading') }}</span>
               </span>
            </h2>
         </template>

         <template v-slot:body>
            <suggest-pane
               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"
               ref="suggestAddress">
            </suggest-pane>
         </template>

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

      </modal>
   </teleport>
   <div class="mt-4" v-else>
      <suggest-pane v-if="flag.suggestPane"
         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"
         ref="suggestAddress">
      </suggest-pane>
   </div>

   <!-- step 2 -->
   <teleport to="body" v-if="inModal">
      <modal v-if="flag.editPane"
         modalDialogClass="modal-dialog-scrollable modal-xl"
         @close="resetPane">

         <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">{{ $t('loading') }}</span>
               </span>
            </h2>
         </template>

         <template v-slot:body>
            <edit-pane
               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-pane>
         </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-pane 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-pane>
   </div>

   <!-- step 3 -->
   <teleport to="body" v-if="inModal">
      <modal v-if="flag.datePane"
             modalDialogClass="modal-dialog-scrollable modal-xl"
             @close="resetPane">

         <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">{{ $t('loading') }}</span>
               </span>
            </h2>
         </template>

         <template v-slot:body>
            <date-pane
               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"
               ref="dateAddress">
            </date-pane>
         </template>

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

      </modal>
   </teleport>
   <div class="mt-4" v-else>
      <date-pane v-if="flag.datePane"
         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"
         ref="dateAddress">
      </date-pane>
   </div>

</template>

<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import { getAddress, fetchCountries, fetchCities, fetchReferenceAddresses, patchAddress, postAddress, postPostalCode } from '../api';
import { postAddressToPerson, postAddressToHousehold } from "ChillPersonAssets/vuejs/_api/AddAddress.js";
import ShowPane from './ShowPane.vue';
import SuggestPane from './SuggestPane.vue';
import EditPane from './EditPane.vue';
import DatePane from './DatePane.vue';

export default {
   name: "AddAddress",
   props: ['context', 'options', 'addressChangedCallback'],
   components: {
      Modal,
      ShowPane,
      SuggestPane,
      EditPane,
      DatePane
   },
   data() {
      return {
         flag: {
            showPane: true, // begin with showPane
            suggestPane: false,
            editPane: false,
            datePane: false,
            loading: false,
            success: false
         },
         default: {
            button: {
               text: { create: 'add_an_address_title', edit: 'edit_address' },
               type: { create: 'btn-create', edit: 'btn-update'},
               displayText: true
            },
            title: { create: 'add_an_address_title', edit: 'edit_address' },
            openPanesInModal: true,
            stickyActions: false,
            useDate: {
               validFrom: false,
               validTo: false
            }
         },
         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
               },
               valid: {
                  from: new Date(),
                  to:  new Date()
               }
            },
            addressMap: {
               // Note: LeafletJs demands [lat, lon]
               // cfr https://macwright.com/lonlat/
               center : [48.8589, 2.3469],
               zoom: 12
            },
         },
         errorMsg: []
      }
   },
   computed: {
      inModal() {
         return (typeof this.options.openPanesInModal !== 'undefined') ?
            this.options.openPanesInModal : this.default.openPanesInModal;
      },
      useDatePane() {
         let vFrom = (typeof this.options.useDate !== 'undefined'
            && typeof this.options.useDate.validFrom !== 'undefined') ?
            this.options.useDate.validFrom : this.default.useDate.validFrom ;
         let vTo = (typeof this.options.useDate !== 'undefined'
            && typeof this.options.useDate.validTo !== 'undefined') ?
            this.options.useDate.validTo : this.default.useDate.validTo ;
         return (vFrom || vTo) ? true : false;
      },
      hasSuggestions() {
         // TODO
         //return addressSuggestions.length > 0
         return true;
      },
      getTextTitle() {
         if ( typeof this.options.title !== 'undefined'
            && ( this.options.title.edit !== null
               || this.options.title.create !== null
            )) {
            return (this.context.edit) ? this.options.title.edit : this.options.title.create;
         }
         return (this.context.edit) ? this.default.title.edit : this.default.title.create;
      },
      bypassFirstStep() {
         // exception: passing step0 if new address and pane are not in modal
         return !this.context.edit && !this.inModal && this.flag.editPane === false
      }
   },
   mounted() {

      //console.log('options displayText', this.options.button.displayText);
      //console.log('options bindModal.step1', this.options.bindModal.step1);
      //console.log('options bindModal.step2', this.options.bindModal.step2);
      //console.log('options useDate.validFrom', this.options.useDate.validFrom);
      //console.log('options useDate.validTo', this.options.useDate.validTo);
      console.log('useDatePane', this.useDatePane);

      //console.log('Mounted now !');
      this.openShowPane();

   },
   methods: {

      /*
      *  Opening and closing Panes when interacting with buttons
      */
      openShowPane() {
         if (this.context.edit) {
            console.log('getInitialAddress');
            this.getInitialAddress(this.context.addressId);
         }
         if (this.bypassFirstStep) {
            this.closeShowPane();
            this.openEditPane();
         } else {
            this.flag.showPane = true;
            console.log('step0: open the Show Panel');
         }
      },
      closeShowPane() {
         // Show pane can be closed only when openPanesInModal is false
         if (!this.inModal) {
            this.flag.showPane = false;
            console.log('step0: close the Show Panel');
         }
      },
      openSuggestPane() {
         this.flag.suggestPane = true;
         console.log('step1: open the Suggestion Panel');
      },
      closeSuggestPane() {
         this.flag.suggestPane = false;
         console.log('step1: close the Suggestion Panel');
      },
      openEditPane() {
         /*
         if (!this.context.edit && this.hasSuggestions) {
            this.openSuggestPane();
         } else {
         }
         */
         this.initForm();
         this.getCountries();
         this.flag.editPane = true;
         console.log('step2: open the Edit panel');
      },
      closeEditPane() {
         this.applyChanges();
         this.flag.editPane = false;
         console.log('step2: close the Edit Panel');
         /*
         if (!this.context.edit && this.useDatePane) {
            this.openDatePane();
         } else {
         }
         */
         this.openShowPane()
      },
      openDatePane() {
         this.flag.datePane = true;
         console.log('step3: open the Date Panel');
      },
      closeDatePane() {
         this.flag.datePane = false;
         console.log('step3: close the Date Panel');
      },
      resetPane() {
         this.flag.suggestPane = false;
         this.flag.editPane = false;
         this.flag.datePane = false;
         this.flag.showPane = true;
      },

      /*
      *  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 (get out step2 edit pane, button valid),
      *  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
            })
            .then(payload => {
                  console.log('payload', payload);
                  this.closePaneAndCallbackSubmit(payload);
               }
            );

         } else {
            this.addNewAddress(newAddress)
            .then(payload => this.closePaneAndCallbackSubmit(payload));
         }
      },

      /*
      *  Async POST transactions,
      *  creating new address, and receive backend datas when promise is resolved
      */
      addNewAddress(payload)
      {
         //console.log('addNewAddress', payload);
         this.flag.loading = true;

         if ('newPostcode' in payload) {

            let postcodeBody = payload.newPostcode;
            if (this.context.entity.name === 'person') {
               postcodeBody = Object.assign(postcodeBody, {'origin': 3});
            }
            return postPostalCode(postcodeBody)
               .then(postalCode =>  {
                  payload.postcode = {'id': postalCode.id };
                  return this.postNewAddress(payload);
               });

         } else {
            return this.postNewAddress(payload);
         }
      },

      postNewAddress(payload) {
         //console.log('postNewAddress', payload);
         return postAddress(payload)
            .then(address => new Promise((resolve, reject) => {
               this.entity.address = address;
               this.flag.loading = false;
               this.flag.success = true;
               resolve({
                  entity: this.context.entity.name,
                  entityId: this.context.entity.id,
                  addressId: this.entity.address.address_id
                  }
               );
            }))
            .catch((error) => {
               this.errorMsg.push(error);
               this.flag.loading = false;
            });
      },

      /*
      *  Async PATCH transactions,
      *  then update existing address with backend datas when promise is resolved
      */
      updateAddress(payload)
      {
         this.flag.loading = true;

         // TODO change the condition because it writes new postal code in edit mode now: !writeNewPostalCode

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

            return postPostalCode(postcodeBody)
               .then(postalCode => {
                  console.log('create new postcode', postalCode.id);
                  payload.newAddress.postcode = {'id': postalCode.id };
                  return this.patchExistingAddress(payload);
               });

         } else {
            return this.patchExistingAddress(payload);
         }
      },

      patchExistingAddress(payload) {
         console.log('patchExistingAddress', payload);
         return patchAddress(payload.addressId, payload.newAddress)
            .then(address => new Promise((resolve, reject) => {
                  this.entity.address = address;
                  this.flag.loading = false;
                  this.flag.success = true;
                  return resolve({
                     entity: this.context.entity.name,
                     entityId: this.context.entity.id,
                     addressId: this.entity.address.address_id
                  });
               })
            )
            .catch((error) => {
               this.errorMsg.push(error);
               this.flag.loading = false;
            });
      },

      /*
      *  Method just add closing pane to the callback method
      *  (get out step1 show pane, submit button)
      */
      closePaneAndCallbackSubmit(payload)
      {
         console.log('close pane and call parent callback method', payload);

         //this.initForm();
         this.flag.showPane = false;

         // callback props method from parent
         this.addressChangedCallback(payload);
      }
   }
}
</script>

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