<template>
  <div
    v-if="field && field.field_type === 'char'"
    :class="['field', { disabled }]"
  >
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <input
      :id="field.name"
      :value="field.value"
      type="text"
      :name="field.name"
      :required="field.is_mandatory"
      @blur="updateStore_extra_form"
    >
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'list'"
    :class="['field', { disabled }]"
  >
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <Dropdown
      :options="field.options"
      :selected="selected_extra_form_list"
      :selection.sync="selected_extra_form_list"
      :required="field.is_mandatory"
      :search="true"
      :clearable="true"
    />
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'pre_recorded_list'"
    :class="['field', { disabled }]"
  >
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <Multiselect
      v-model="selectedPrerecordedValue"
      :options="
        selectedPrerecordedListValues[field.options[0]] ? selectedPrerecordedListValues[field.options[0]] : []
      "
      :options-limit="10"
      :allow-empty="!field.is_mandatory"
      track-by="label"
      label="label"
      :reset-after="false"
      select-label=""
      selected-label=""
      deselect-label=""
      :searchable="true"
      :placeholder="'Recherchez une valeur de la liste pré-définie ...'"
      :show-no-results="true"
      :loading="loadingPrerecordedListValues"
      :clear-on-select="false"
      :preserve-search="false"
      @search-change="search"
      @select="selectPrerecordedValue"
    >
      <template slot="clear">
        <div
          v-if="selectedPrerecordedValue"
          class="multiselect__clear"
          @click.prevent.stop="clearPrerecordedValue"
        >
          <i
            class="close icon"
            aria-hidden="true"
          />
        </div>
      </template>
      <span slot="noResult">
        Aucun résultat.
      </span>
      <span slot="noOptions">
        Saisissez les premiers caractères ...
      </span>
    </Multiselect>
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'multi_choices_list'"
    :class="['field', { disabled }]"
  >
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <div class="checkbox_list">
      <div
        v-for="option in field.options"
        :key="option"
        class="ui checkbox"
      >
        <input
          :id="option"
          type="checkbox"
          :checked="field.value && field.value.includes(option)"
          :name="option"
          @change="selectMultipleCheckbox"
        >
        <label :for="option">
          {{ option }}
        </label>
      </div>
    </div>
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'integer'"
    :class="['field', { disabled }]"
  >
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <div class="ui input">
      <!-- //* si click sur fléche dans champ input, pas de focus, donc pas de blur, donc utilisation de @change -->
      <input
        :id="field.name"
        :value="field.value"
        type="number"
        :name="field.name"
        :required="field.is_mandatory"
        @change="updateStore_extra_form"
      >
    </div>
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'boolean'"
    :class="['field', { disabled }]"
  >
    <div :class="['ui checkbox', { disabled }]">
      <input
        :id="field.name"
        type="checkbox"
        :checked="field.value"
        :name="field.name"
        @change="updateStore_extra_form"
      >
      <label :for="field.name">
        {{ displayLabels ? field.label : '' }}
      </label>
    </div>
  </div>

  <div
    v-else-if="field && field.field_type === 'date'"
    :class="['field', { disabled }]"
  >
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <input
      :id="field.name"
      :value="field.value"
      type="date"
      :name="field.name"
      :required="field.is_mandatory"
      @change="updateStore_extra_form"
    >
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'decimal'"
    :class="['field', { disabled }]"
  >
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <div class="ui input">
      <input
        :id="field.name"
        :value="field.value"
        type="number"
        step=".01"
        :name="field.name"
        :required="field.is_mandatory"
        @change="updateStore_extra_form"
      >
    </div>
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'text'"
    :class="['field', { disabled }]"
  >
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <textarea
      :value="field.value"
      :name="field.name"
      :required="field.is_mandatory"
      rows="3"
      @blur="updateStore_extra_form"
    />
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>
</template>

<script>
import { mapState, mapActions, mapMutations } from 'vuex';
import Multiselect from 'vue-multiselect';
import { isEqual } from 'lodash';

import Dropdown from '@/components/Dropdown.vue';

export default {
  name: 'FeatureExtraForm',

  components: {
    Dropdown,
    Multiselect
  },

  props: {
    field: {
      type: Object,
      default: null,
    },
    isConditionalField: {
      type: Boolean,
      default: false,
    }
  },

  data() {
    return {
      error: null,
      prerecordedListSearchQuery: null,
      loadingPrerecordedListValues: false,
      selectedPrerecordedValue: null,
      selectedMultipleCheckbox: [],
    };
  },

  computed: {
    ...mapState('feature-type', [
      'selectedPrerecordedListValues'
    ]),
    ...mapState('feature', [
      'extra_forms',
    ]),

    selected_extra_form_list: {
      get() {
        return this.field.value || '';
      },
      set(newValue) {
        //* set the value selected in the dropdown
        if (this.isConditionalField) {
          this.$emit('update:condition-value', newValue);
        } else {
          const newExtraForm = this.field;
          newExtraForm['value'] = newValue;
          this.$store.commit('feature/UPDATE_EXTRA_FORM', newExtraForm);
        }
      },
    },

    displayLabels() {
      return this.$route.name === 'editer-signalement' || this.$route.name === 'ajouter-signalement' || this.$route.name === 'editer-attribut-signalement';
    },

    disabled () {
      return this.field.disabled;
    }
  },

  watch: {
    'field.value': function(newValue, oldValue) {
      // In fast edition, prerecordedlist is not updated, thus the value stay the same
      // in this case we renitialize the field. This doesn't impact usual behavior if user reselect the same option
      if (this.field) {
        if (this.field.field_type === 'pre_recorded_list') {
          // if both values are defined but their values changed, value in form should be updated
          if (newValue && oldValue && newValue.label !== oldValue.label
          // if any of them is undefined, the form value should be updated, because in this case the value changed
          // otherwise (if they are both undefined) the watcher would not called, thus we don't need to prevent this case
          || !newValue || !oldValue)
          {
            this.initPrerecordedXform();
          }
        } else if (this.field.field_type === 'multi_choices_list') {
          // if array values changed, value in form should be updated, otherwise at edition in fast browsing mode, it would overide current value with previous value loaded at component creation
          if (isEqual(newValue, oldValue)){
            this.initMultipleCheckboxXform();
          }
        }
        this.error = null;
      }
    },

    prerecordedListSearchQuery(newValue) {
      this.loadingPrerecordedListValues = true;
      this.GET_SELECTED_PRERECORDED_LIST_VALUES({
        name: this.field.options[0],
        pattern: newValue
      })
        .then(() => {
          this.loadingPrerecordedListValues = false;
        })
        .catch(() => {
          this.loadingPrerecordedListValues = false;
        });
    }
  },

  created() {
    if (this.field) {
      if (this.field.field_type === 'pre_recorded_list') {
        this.initPrerecordedXform();
      } else if (this.field.field_type === 'multi_choices_list') {
        this.initMultipleCheckboxXform();
      }
    }
  },
  
  mounted() {
    // autoset field to false if is a boolean, since user doesn't need to select it, when false value is expected
    if (this.field.field_type === 'boolean' && (this.field.value === undefined || this.field.value === null)) {
      this.updateStore_extra_form(false);
    }
  },

  methods: {
    ...mapActions('feature-type', [
      'GET_SELECTED_PRERECORDED_LIST_VALUES'
    ]),
    ...mapMutations('feature', [
      'UPDATE_EXTRA_FORM',
      'SET_EXTRA_FORMS',
    ]),

    initMultipleCheckboxXform() {
      this.selectedMultipleCheckbox = this.field.value || [];
    },

    initPrerecordedXform() {
      const { options, value } = this.field;
      this.loadingPrerecordedListValues = true;
      this.GET_SELECTED_PRERECORDED_LIST_VALUES({
        name: options[0],
        pattern: ''
      })
        .then(() => {
          this.loadingPrerecordedListValues = false;
        })
        .catch(() => {
          this.loadingPrerecordedListValues = false;
        });
      if (value) {
        this.selectedPrerecordedValue = { label: value.label ? value.label : value };
      } else {
        this.selectedPrerecordedValue = null;
      }
    },

    updateStore_extra_form(evt) {
      if (this.field) {
        let newValue;
        if (evt && evt.target) { // if called from the template
          if (this.field.field_type === 'boolean') {
            newValue = evt.target.checked; //* if checkbox, use "checked"
          } else {
            newValue = evt.target.value;
          }
        } else if (this.field.field_type === 'multi_choices_list') { // special case where the value is stored in the state
          newValue = this.selectedMultipleCheckbox;
        } else { // if the newValue was sent directly
          newValue = evt;
        }
        //* set the value selected
        if (this.isConditionalField) {
          this.$emit('update:condition-value', newValue);
        } else {
          this.UPDATE_EXTRA_FORM({ ...this.field, ['value']: newValue });
        }
      }
    },

    checkForm() {
      let isValid = true;
      if (this.field && this.field.is_mandatory && !this.field.value) {
        isValid = false;
        this.error = 'Ce champ est obligatoire';
      } else {
        this.error = null;
      }
      return isValid;
    },

    search(text) {
      this.prerecordedListSearchQuery = text;
    },

    selectPrerecordedValue(e) {
      this.selectedPrerecordedValue = e;
      this.prerecordedListSearchQuery = null;
      this.updateStore_extra_form({ target: { value:  this.selectedPrerecordedValue } });
    },
    
    clearPrerecordedValue() {
      this.selectedPrerecordedValue = null;
      this.prerecordedListSearchQuery = null;
      this.updateStore_extra_form({ target: { value:  null } });
    },

    selectMultipleCheckbox(e) {
      const { checked, name } = e.target;
      if (checked) {
        this.selectedMultipleCheckbox.push(name);
      } else {
        this.selectedMultipleCheckbox = this.selectedMultipleCheckbox.filter((el) => el !== name);
      }
      this.updateStore_extra_form();
    },
  },
};
</script>

<style lang="less" scoped>

label.required:after {
	content: ' *';
	color: rgb(209, 0, 0);
}
.checkbox_list {
  display: flex;
  flex-direction: column;
  .ui.checkbox {
    margin: .5rem;
    font-weight: normal;
  }
}
</style>

<style>
/* keep placeholder width when opening dropdown */
.multiselect {
  width: 305px;
}
/* keep font-weight from overide of semantic classes */
.multiselect__placeholder, .multiselect__content, .multiselect__tags  {
  font-weight: initial !important;
}
/* keep placeholder eigth */
.multiselect .multiselect__placeholder {
  margin-bottom: 9px !important;
  padding-top: 1px;
}
/* keep placeholder height when opening dropdown without selection */
input.multiselect__input {
  padding: 3px 0 0 0 !important;
}
/* keep placeholder height when opening dropdown with already a value selected */
.multiselect__tags .multiselect__single {
  padding: 1px 0 0 0 !important;
  margin-bottom: 9px;
}
</style>