<template>
  <form @submit.prevent="submit">
    <FormRow>
      <FormInput
        v-model="$v.values.name.$model"
        :label="$t('updateUserSourceForm.nameFieldLabel')"
        class="update-user-source-form__name-input"
        :placeholder="$t('updateUserSourceForm.nameFieldPlaceholder')"
        :error="getError('name')"
      />
      <FormGroup
        :label="$t('updateUserSourceForm.integrationFieldLabel')"
        :error="getError('integration_id')"
      >
        <IntegrationDropdown
          v-model="$v.values.integration_id.$model"
          :application="builder"
          :integrations="integrations"
          :integration-type="userSourceType.integrationType"
        />
      </FormGroup>
    </FormRow>
    <component
      :is="userSourceType.formComponent"
      v-if="integration"
      :default-values="defaultValues"
      :application="builder"
      :integration="integration"
      @values-changed="emitChange"
    />
    <div v-if="integration">
      <h4>{{ $t('updateUserSourceForm.authTitle') }}</h4>

      <div v-for="appAuthType in appAuthProviderTypes" :key="appAuthType.type">
        <Checkbox
          :checked="hasAtLeastOneOfThisType(appAuthType)"
          @input="onSelect(appAuthType)"
        >
          {{ appAuthType.name }}
        </Checkbox>
        <div
          v-for="appAuthProvider in appAuthProviderPerTypes[appAuthType.type]"
          :key="appAuthProvider.id"
          class="update-user-source-form__auth-provider-form"
        >
          <component
            :is="appAuthType.formComponent"
            v-if="hasAtLeastOneOfThisType(appAuthType)"
            :integration="integration"
            :current-user-source="fullValues"
            :default-values="appAuthProvider"
            excluded-form
            @values-changed="updateAuthProvider(appAuthProvider, $event)"
          />
        </div>
      </div>
    </div>
    <input type="submit" hidden />
  </form>
</template>

<script>
import form from '@baserow/modules/core/mixins/form'
import IntegrationDropdown from '@baserow/modules/core/components/integrations/IntegrationDropdown'
import { required, maxLength } from 'vuelidate/lib/validators'
import { uuid } from '@baserow/modules/core/utils/string'

export default {
  components: { IntegrationDropdown },
  mixins: [form],
  props: {
    builder: {
      type: Object,
      required: true,
    },
    userSourceType: {
      type: Object,
      required: false,
      default: null,
    },
    integrations: {
      type: Array,
      required: true,
    },
  },
  data() {
    return {
      values: {
        integration_id: null,
        name: '',
        auth_providers: [],
      },
      fullValues: this.getFormValues(),
    }
  },
  computed: {
    integration() {
      if (!this.values.integration_id) {
        return null
      }
      return this.integrations.find(
        ({ id }) => id === this.values.integration_id
      )
    },
    appAuthProviderTypes() {
      return this.$registry.getOrderedList('appAuthProvider')
    },
    appAuthProviderPerTypes() {
      return Object.fromEntries(
        this.appAuthProviderTypes.map((authType) => {
          return [
            authType.type,
            this.values.auth_providers.filter(
              ({ type }) => type === authType.type
            ),
          ]
        })
      )
    },
  },
  methods: {
    // Override the default getChildFormValues to exclude the provider forms from
    // final values as they are handled directly by this component
    getChildFormsValues() {
      return Object.assign(
        {},
        ...this.$children
          .filter(
            (child) =>
              'getChildFormsValues' in child &&
              child.$attrs['excluded-form'] === undefined
          )
          .map((child) => {
            return child.getFormValues()
          })
      )
    },
    hasAtLeastOneOfThisType(appAuthProviderType) {
      return this.appAuthProviderPerTypes[appAuthProviderType.type]?.length > 0
    },
    onSelect(appAuthProviderType) {
      if (this.hasAtLeastOneOfThisType(appAuthProviderType)) {
        this.values.auth_providers = this.values.auth_providers.filter(
          ({ type }) => type !== appAuthProviderType.type
        )
      } else {
        this.values.auth_providers.push({
          type: appAuthProviderType.type,
          id: uuid(),
        })
      }
    },
    updateAuthProvider(authProviderToChange, values) {
      this.values.auth_providers = this.values.auth_providers.map(
        (authProvider) => {
          if (authProvider.id === authProviderToChange.id) {
            return { ...authProvider, ...values }
          }
          return authProvider
        }
      )
    },
    emitChange() {
      this.fullValues = this.getFormValues()
    },
    getError(fieldName) {
      if (!this.$v.values[fieldName].$dirty) {
        return ''
      }
      const fieldState = this.$v.values[fieldName]
      if (!fieldState.required) {
        return this.$t('error.requiredField')
      }
      if (fieldName === 'name' && !fieldState.maxLength) {
        return this.$t('error.maxLength', { max: 255 })
      }
      return ''
    },
  },
  validations: {
    values: {
      integration_id: {
        required,
      },
      name: {
        required,
        maxLength: maxLength(255),
      },
    },
  },
}
</script>