<template>
   <a class="btn" :class="getClassButton" :title="$t(buttonTitle)" @click="openModal">
      <span v-if="displayTextButton">{{ $t(buttonTitle) }}</span>
   </a>

  <teleport to="body">
      <modal v-if="modal.showModal"
         :modalDialogClass="modal.modalDialogClass"
         @close="modal.showModal = false">

         <template v-slot:header>
            <h3 class="modal-title">{{ $t(modalTitle) }}</h3>
         </template>

         <template v-slot:body-head>
            <div class="modal-body">
               <div class="search">

                  <label class="col-form-label" style="float: right;">
                     {{ $tc('add_persons.suggested_counter', suggestedCounter) }}
                  </label>

                  <input id="search-persons"
                     name="query"
                     v-model="query"
                     :placeholder="$t('add_persons.search_some_persons')"
                     ref="search" />
                  <i class="fa fa-search fa-lg"></i>
                  <i class="fa fa-times" v-if="queryLength >= 3" @click="resetSuggestion"></i>

               </div>
            </div>
            <div class="modal-body" v-if="checkUniq === 'checkbox'">
               <div class="count">
                  <span>
                     <a v-if="suggestedCounter > 2" @click="selectAll">
                        {{ $t('action.check_all')}}
                     </a>
                     <a v-if="selectedCounter > 0" @click="resetSelection">
                        <i v-if="suggestedCounter > 2"> • </i>
                        {{ $t('action.reset')}}
                     </a>
                  </span>
                  <span v-if="selectedCounter > 0">
                     {{ $tc('add_persons.selected_counter', selectedCounter) }}
                  </span>
               </div>
            </div>
         </template>

         <template v-slot:body>
            <div class="results">

               <person-suggestion
                  v-for="item in this.selectedAndSuggested.slice().reverse()"
                  v-bind:key="itemKey(item)"
                  v-bind:item="item"
                  v-bind:search="search"
                  v-bind:type="checkUniq"
                  @saveFormOnTheFly="saveFormOnTheFly"
                  @newPriorSuggestion="newPriorSuggestion"
                  @updateSelected="updateSelected">
               </person-suggestion>

               <div class="create-button">
                  <on-the-fly
                     v-if="queryLength >= 3 && (options.type.includes('person') || options.type.includes('thirdparty'))"
                     :buttonText="$t('onthefly.create.button', {q: query})"
                     :allowedTypes="options.type"
                     :query="query"
                     action="create"
                     @saveFormOnTheFly="saveFormOnTheFly"
                     ref="onTheFly">
                  </on-the-fly>
               </div>

            </div>
         </template>

         <template v-slot:footer>
            <button class="btn btn-create"
               @click.prevent="$emit('addNewPersons', { selected, modal })">
               {{ $t('action.add')}}
            </button>
         </template>

      </modal>
   </teleport>
</template>

<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
import PersonSuggestion from './AddPersons/PersonSuggestion';
import { searchEntities } from 'ChillPersonAssets/vuejs/_api/AddPersons';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';

export default {
   name: 'AddPersons',
   components: {
      Modal,
      PersonSuggestion,
      OnTheFly
   },
   props: [
      'buttonTitle',
      'modalTitle',
      'options'
   ],
   emits: ['addNewPersons'],
   data() {
      return {
         modal: {
            showModal: false,
            modalDialogClass: "modal-dialog-scrollable modal-xl"
         },
         search: {
            query: "",
            previousQuery: "",
            currentSearchQueryController: null,
            suggested: [],
            selected: [],
            priorSuggestion: {}
         },
      }
   },
   computed: {
      query: {
         set(query) {
            return this.setQuery(query);
         },
         get() {
            return this.search.query;
         }
      },
      queryLength() {
         return this.search.query.length;
      },
      suggested() {
         return this.search.suggested;
      },
      suggestedCounter() {
         return this.search.suggested.length;
      },
      selected() {
         return this.search.selected;
      },
      selectedCounter() {
         return this.search.selected.length;
      },
      selectedAndSuggested() {
         this.addPriorSuggestion();
         const uniqBy = (a, key) => [
               ...new Map(
                  a.map(x => [key(x), x])
               ).values()
         ];
         let union = [...new Set([
            ...this.suggested.slice().reverse(),
            ...this.selected.slice().reverse(),
         ])];
         return uniqBy(union, k => k.key);
      },
      getClassButton() {
         let size = (typeof this.options.button !== 'undefined' && typeof this.options.button.size !== 'undefined') ? this.options.button.size : '';
         let type = (typeof this.options.button !== 'undefined' && typeof this.options.button.type !== 'undefined') ? this.options.button.type : 'btn-create';
         return size ? size + ' ' + type : type;
      },
      displayTextButton() {
         return (typeof this.options.button !== 'undefined' && typeof this.options.button.display !== 'undefined') ?
            this.options.button.display : true;
      },
      checkUniq() {
         if (this.options.uniq === true) {
            return 'radio';
         }
         return 'checkbox';
      },
      priorSuggestion() {
         return this.search.priorSuggestion;
      },
      hasPriorSuggestion() {
         return this.search.priorSuggestion.key ? true : false;
      },
   },
   methods: {
      openModal() {
         this.modal.showModal = true;
         this.$nextTick(function() {
            this.$refs.search.focus();
         })
      },
      setQuery(query) {
         this.search.query = query;

         setTimeout(function() {
            if (query === "") {
               this.loadSuggestions([]);
               return;
            }
            if (query === this.search.query) {
               if (this.currentSearchQueryController !== undefined) {
                  this.currentSearchQueryController.abort()
               }
               this.currentSearchQueryController = new AbortController();
               searchEntities({ query, options: this.options }, this.currentSearchQueryController)
                  .then(suggested => new Promise((resolve, reject) => {
                     this.loadSuggestions(suggested.results);
                     resolve();
                  }));
            }
         }.bind(this), query.length > 3 ? 300 : 700);
      },
      loadSuggestions(suggested) {
         this.search.suggested = suggested;
         this.search.suggested.forEach(function(item) {
            item.key = this.itemKey(item);
         }, this);
      },
      updateSelected(value) {
         //console.log('value', value);
         this.search.selected = value;
      },
      resetSearch() {
         this.resetSelection();
         this.resetSuggestion();
      },
      resetSuggestion() {
         this.search.query = "";
         this.search.suggested = [];
      },
      resetSelection() {
         this.search.selected = [];
      },
      selectAll() {
         this.search.suggested.forEach(function(item) {
            this.search.selected.push(item);
         }, this);
      },
      itemKey(item) {
         return item.result.type + item.result.id;
      },
      addPriorSuggestion() {
         // console.log('prior suggestion', this.priorSuggestion);
         if (this.hasPriorSuggestion) {
            // console.log('addPriorSuggestion',);
            this.suggested.unshift(this.priorSuggestion);
            this.selected.unshift(this.priorSuggestion);

            this.newPriorSuggestion(null);
         }
      },
      newPriorSuggestion(entity) {
         // console.log('newPriorSuggestion', entity);
         if (entity !== null) {
            let suggestion = {
               key: entity.type + entity.id,
               relevance: 0.5,
               result: entity
            }
            this.search.priorSuggestion = suggestion;
            // console.log('search priorSuggestion', this.search.priorSuggestion);
            this.addPriorSuggestion(suggestion);
         } else {
            this.search.priorSuggestion = {};
         }
      },
      saveFormOnTheFly({ type, data }) {
         // console.log('saveFormOnTheFly from addPersons, type', type, ', data', data);
         if (type === 'person') {
            makeFetch('POST', '/api/1.0/person/person.json', data)
               .then(response => {
                  this.newPriorSuggestion(response);
                  this.$refs.onTheFly.closeModal();
               })
               .catch((error) => {
                  if (error.name === 'ValidationException') {
                     for (let v of error.violations) {
                        this.$toast.open({message: v });
                     }
                  } else {
                     this.$toast.open({message: 'An error occurred'});
                  }
               })
         }
         else if (type === 'thirdparty') {
            makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data)
               .then(response => {
                  this.newPriorSuggestion(response);
                  this.$refs.onTheFly.closeModal();
               })
               .catch((error) => {
                  if (error.name === 'ValidationException') {
                     for (let v of error.violations) {
                        this.$toast.open({message: v });
                     }
                  } else {
                     this.$toast.open({message: 'An error occurred'});
                  }
               })
         }
      }
   },
}
</script>

<style lang="scss">
   li.add-persons {
      a {
         cursor: pointer;
      }
   }
   div.body-head {
      overflow-y: unset;
      div.modal-body:first-child {
         margin: auto 4em;
         div.search {
            position: relative;
            input {
               width: 100%;
               padding: 1.2em 1.5em 1.2em 2.5em;
               //margin: 1em 0;
            }
            i {
               position: absolute;
               opacity: 0.5;
               padding: 0.65em 0;
               top: 50%;
            }
            i.fa-search {
               left: 0.5em;
            }
            i.fa-times {
               right: 1em;
               padding: 0.75em 0;
               cursor: pointer;
            }
         }
      }
      div.modal-body:last-child {
         padding-bottom: 0;
      }
      div.count {
         margin: -0.5em 0 0.7em;
         display: flex;
         justify-content: space-between;
         a {
            cursor: pointer;
         }
      }
   }
   .create-button > a {
      margin-top: 0.5em;
      margin-left: 2.6em;
   }
</style>
