<template>
  <!-- Show user source list -->
  <div
    v-if="!showCreateForm && editedUserSource === null"
    class="user-sources-settings"
  >
    <h2 class="box__title">{{ $t('userSourceSettings.titleOverview') }}</h2>
    <Error :error="error"></Error>
    <div v-if="!error.visible" class="actions actions--right">
      <Button icon="iconoir-plus" @click="showForm()">
        {{ $t('userSourceSettings.addUserSource') }}
      </Button>
    </div>
    <div
      v-for="userSource in userSources"
      :key="userSource.id"
      class="user-source-settings__user-source"
      @delete="deleteUserSource(userSource)"
    >
      <Presentation
        :image="getUserSourceType(userSource).image"
        :title="userSource.name"
        :subtitle="getUserSourceType(userSource).getSummary(userSource)"
        :rounded-icon="false"
        avatar-color="transparent"
        style="flex: 1"
      />
      <div class="user-source-settings__user-source-actions">
        <ButtonIcon icon="iconoir-edit" @click="showForm(userSource)" />
        <ButtonIcon icon="iconoir-bin" @click="deleteUserSource(userSource)" />
      </div>
    </div>
    <p v-if="!error.visible && userSources.length === 0" class="margin-top-3">
      {{ $t('userSourceSettings.noUserSourceMessage') }}
    </p>
  </div>
  <!-- Edit user source -->
  <div v-else-if="editedUserSource">
    <h2 class="box__title">
      {{ $t('userSourceSettings.titleUpdateUserSource') }}
    </h2>
    <Error :error="error"></Error>

    <Presentation
      :image="getUserSourceType(editedUserSource).image"
      :title="getUserSourceType(editedUserSource).name"
      :rounded-icon="false"
      avatar-color="transparent"
      style="flex: 1; margin-bottom: 18px"
      icon-size="medium"
    />

    <UpdateUserSourceForm
      ref="userSourceForm"
      :builder="builder"
      :user-source-type="getUserSourceType(editedUserSource)"
      :default-values="editedUserSource"
      @submitted="updateUserSource"
      @values-changed="onValueChange"
    />
    <div class="actions">
      <ButtonText
        type="secondary"
        icon="iconoir-nav-arrow-left"
        @click="editedUserSource = null"
      >
        {{ $t('action.back') }}
      </ButtonText>
      <Button
        :disabled="actionInProgress || invalidForm"
        :loading="actionInProgress"
        size="large"
        @click="$refs.userSourceForm.submit(true)"
      >
        {{ $t('action.save') }}
      </Button>
    </div>
  </div>
  <!-- Create user source -->
  <div v-else>
    <h2 class="box__title">
      {{ $t('userSourceSettings.titleAddUserSource') }}
    </h2>
    <Error :error="error"></Error>
    <CreateUserSourceForm
      ref="userSourceForm"
      :builder="builder"
      @submitted="createUserSource"
      @values-changed="onValueChange"
    />
    <div class="actions">
      <ButtonText
        type="secondary"
        icon="iconoir-nav-arrow-left"
        @click="hideForm"
      >
        {{ $t('action.back') }}
      </ButtonText>
      <Button
        :disabled="actionInProgress || invalidForm"
        :loading="actionInProgress"
        size="large"
        @click="$refs.userSourceForm.submit()"
      >
        {{ $t('action.create') }}
      </Button>
    </div>
  </div>
</template>

<script>
import { mapActions } from 'vuex'
import error from '@baserow/modules/core/mixins/error'
import { clone } from '@baserow/modules/core/utils/object'
import { notifyIf } from '@baserow/modules/core/utils/error'
import CreateUserSourceForm from '@baserow/modules/builder/components/userSource/CreateUserSourceForm'
import UpdateUserSourceForm from '@baserow/modules/builder/components/userSource/UpdateUserSourceForm'

export default {
  name: 'UserSourceSettings',
  components: { CreateUserSourceForm, UpdateUserSourceForm },
  mixins: [error],
  provide() {
    return { builder: this.builder }
  },
  props: {
    builder: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      showCreateForm: false,
      editedUserSource: null,
      actionInProgress: false,
      invalidForm: false,
    }
  },
  computed: {
    integrations() {
      return this.$store.getters['integration/getIntegrations'](this.builder)
    },
    userSources() {
      return this.$store.getters['userSource/getUserSources'](this.builder)
    },
    userSourceTypes() {
      return this.$registry.getAll('userSource')
    },
  },
  async mounted() {
    try {
      await Promise.all([
        this.actionFetchIntegrations({
          application: this.builder,
        }),
      ])
    } catch (error) {
      notifyIf(error)
    }
  },
  methods: {
    ...mapActions({
      actionFetchIntegrations: 'integration/fetch',
      actionCreateUserSource: 'userSource/create',
      actionUpdateUserSource: 'userSource/update',
      actionDeleteUserSource: 'userSource/delete',
    }),
    getUserSourceType(userSource) {
      return this.$registry.get('userSource', userSource.type)
    },
    onValueChange() {
      this.invalidForm = !this.$refs.userSourceForm.isFormValid(true)
    },
    async showForm(userSourceToEdit) {
      if (userSourceToEdit) {
        this.editedUserSource = userSourceToEdit
      } else {
        this.showCreateForm = true
      }
      await this.$nextTick()
      this.onValueChange()
    },
    hideForm() {
      this.showCreateForm = false
      this.editedUserSource = null
      this.hideError()
      this.invalidForm = false
    },
    async createUserSource(values) {
      this.actionInProgress = true
      const { type, ...rest } = values
      try {
        const createdUserSource = await this.actionCreateUserSource({
          application: this.builder,
          userSourceType: type,
          values: rest,
        })

        this.hideForm()
        // immediately select this user source to edit it.
        this.editedUserSource = createdUserSource
      } catch (error) {
        this.handleError(error)
      }
      this.actionInProgress = false
    },
    async updateUserSource(newValues) {
      if (!this.$refs.userSourceForm.isFormValid(true)) {
        return
      }

      this.actionInProgress = true
      try {
        await this.actionUpdateUserSource({
          application: this.builder,
          userSourceId: this.editedUserSource.id,
          values: clone(newValues),
        })
        this.hideForm()
      } catch (error) {
        // Restore the previously saved values from the store
        if (!this.$refs.userSourceForm.handleServerError(error)) {
          this.$refs.userSourceForm.reset()
          this.handleError(error)
        }
      }
      this.actionInProgress = false
    },
    async deleteUserSource(userSource) {
      try {
        await this.actionDeleteUserSource({
          application: this.builder,
          userSourceId: userSource.id,
        })
      } catch (error) {
        notifyIf(error)
      }
    },
  },
}
</script>