<template>
  <itf-modal
    ref="modal"
    :data-test="dataTest"
    append-to-body
    :visible="value"
    persistent
    close-icon
    :fullscreen="fullscreen"
    :title="title"
    content
    :size="size"
    @keydown.native.shift.enter.stop.prevent="submitSaveItem()"
    @update:visible="$emit('input', $event)"
    @close="onClose"
  >
    <itf-alert
      v-if="showError"
      outlined
      type="danger"
      dismissible
      :message="errorMessage"
    />

    <itf-form v-if="showContent" ref="form">
      <slot />
    </itf-form>

    <slot name="after-body" />

    <template #footer>
      <slot name="footer">
        <itf-delete-confirm-popover v-if="canDelete" :loading="loading" @delete="deleteItem">
          <template #activator="{ on }">
            <itf-button color="outline-danger" v-on="on">
              {{ $t('components.modal.delete') }}
            </itf-button>
          </template>
        </itf-delete-confirm-popover>
        <slot name="help"></slot>

        <div class="itf-spacer" />

        <itf-button
          v-if="!readonly"
          data-test="item-editor-cancel"
          :disabled="loading"
          default
          class="me-2"
          @click="$emit('input', false)"
        >
          <span class="me-1">{{ $t('components.modal.cancel') }}</span>
        </itf-button>

        <slot
          name="save-btn"
          :loading="loading"
        >
          <itf-button
            primary
            data-test="item-editor-save"
            :disabled="loading"
            :loading="loading"
            @click="submitSaveItem()"
          >
            <span class="me-1">{{ saveBtnCaption }}</span>
          </itf-button>
        </slot>
      </slot>
    </template>
  </itf-modal>
</template>
<script>
import { Vue, Component, Model, Prop, Watch, Provide } from 'vue-property-decorator';
import itfAlert from '../alert/Alert';
import itfForm from '../form/Form';
import itfModal from '../modal/Modal';
import itfButton from '../button/Button';
import itfIcon from '../icon/Icon';
import itfDeleteConfirmPopover from '../popover/DeleteConfirmPopover.vue';

export default @Component({
  components: {
    itfIcon,
    itfAlert,
    itfForm,
    itfModal,
    itfButton,
    itfDeleteConfirmPopover
  }
})
class itfItemEditor extends Vue {
  @Provide('itemEditorForm')
  getForm () {
    return this.$refs.form;
  }

  @Model('input') value;
  @Prop({ type: String, default () { return this.$t('components.modal.itemHasBeenSuccessfullySaved'); } }) successMessage;
  @Prop({ type: String, default () { return this.$t('components.modal.itemHasBeenSuccessfullyDeleted'); } }) successDeleteMessage;
  @Prop() saveFunc;
  @Prop() deleteFunc;
  @Prop() dataTest;
  @Prop(String) title;
  @Prop({ type: String, default () { return this.$t('components.modal.save'); } }) saveBtnCaption;
  @Prop({ type: String, default: 'lg' }) size;
  @Prop(Boolean) canDelete;
  @Prop(Boolean) fullscreen;
  @Prop(Boolean) readonly; // показує форму, але кнопка Save не викликає saveFunc

  loading = false;
  showError = false;
  showContent = false;

  errorMessage = null;

  details = {};

  mounted () {
    this.onShowChange();
  }

  resetValidation () {
    this.$refs.form.resetValidation();
  }

  reassignFormInputs (form) {
    const inputs = [];
    // Copied from VForm's previous life* which had a getInputs() function
    const search = (children, depth = 0) => {
      for (let index = 0; index < children.length; index++) {
        const child = children[index];
        if (child.errorBucket !== undefined) { inputs.push(child); } else { search(child.$children, depth + 1); }
      }
      if (depth === 0) { return inputs; }
    };
    search(form.$children);
    form.components = inputs;
  }

  async submitSaveItem (successCallback) {
    if (!this.$refs.form) {
      return;
    }
    this.reassignFormInputs(this.$refs.form); // це потрібно щоб працювала валідація вкладених v-form, наприклад, кастомні поля

    if (!this.readonly && !this.$refs.form.doValidation()) {
      this.$refs.modal.scrollModalTop();
      return;
    }
    if (this.loading) {
      return;
    }

    this.loading = true;
    this.showError = false;

    try {
      if (!this.readonly) {
        const data = await this.saveFunc();
        if (this.successMessage) {
          this.$showSuccess(this.successMessage);
        }
        setTimeout(() => {
          this.$emit('saved', data);
          if (typeof successCallback === 'function') {
            successCallback();
          }
        }, 600); // modal animation 500 + 100 delay
      }
      this.$emit('input', false);
    } catch (err) {
      this.$emit('save-error');
      this.errorMessage = err.message || this.$t('components.modal.networkProblem');
      this.$refs.modal && this.$refs.modal.scrollModalTop();
      this.$showError(this.$t('components.modal.pleaseFixTheErrorsBelowToProceed'));

      this.showError = true;
    }
    this.loading = false;
  }

  async deleteItem () {
    this.loading = true;
    this.showError = false;

    try {
      const data = await this.deleteFunc();

      this.$emit('deleted', data);

      this.$emit('input', false);

      this.$showSuccess(this.successDeleteMessage);
    } catch (err) {
      this.errorMessage = err.message || this.$t('components.modal.networkProblem');

      this.showError = true;
    }
    this.loading = false;
  }

  @Watch('value')
  onShowChange () {
    this.$nextTick(() => this.$refs.form && this.$refs.form.resetValidation());
    this.showError = false;
    if (this.value) {
      this.showContent = true;
    }
  }

  onClose() {
    this.showContent = false;
  }
}
</script>
