<template>
  <div>
    <FormGroup
      :label="$t('tablePasteImporter.pasteLabel')"
      small-label
      :error="fieldHasErrors('content')"
      class="margin-bottom-2"
      required
      :helper-text="$t('tablePasteImporter.pasteDescription')"
    >
      <FormTextarea
        v-model="v$.values.content.$model"
        :rows="10"
        @input="changed($event)"
      ></FormTextarea>

      <template #error>{{ v$.values.content.$errors[0]?.$message }}</template>
    </FormGroup>

    <FormGroup
      :label="$t('tablePasteImporter.firstRowHeader')"
      small-label
      class="margin-bottom-2"
      required
    >
      <Checkbox v-model="firstRowHeader" @input="reload()">
        {{ $t('common.yes') }}
      </Checkbox>
    </FormGroup>

    <div v-if="values.filename !== ''" class="control margin-top-0">
      <slot name="upsertMapping" />
    </div>

    <Alert v-if="error !== ''" type="error">
      <template #title> {{ $t('common.wrong') }} </template>
      {{ error }}
    </Alert>
  </div>
</template>

<script>
import { required, helpers } from '@vuelidate/validators'
import { useVuelidate } from '@vuelidate/core'

import form from '@baserow/modules/core/mixins/form'
import importer from '@baserow/modules/database/mixins/importer'

export default {
  name: 'TablePasteImporter',
  mixins: [form, importer],
  setup() {
    return { v$: useVuelidate({ $lazy: true }) }
  },
  data() {
    return {
      firstRowHeader: true,
      values: {
        content: '',
      },
    }
  },
  validations() {
    return {
      values: {
        content: {
          required: helpers.withMessage(
            this.$t('error.requiredField'),
            required
          ),
        },
      },
    }
  },
  methods: {
    changed(content) {
      this.$emit('changed')
      this.resetImporterState()
      this.values.content = content
      this.reload()
    },
    async reload() {
      if (this.values.content === '') {
        this.resetImporterState()
        return
      }
      const limit = this.$config.INITIAL_TABLE_DATA_LIMIT
      const count = this.values.content.split(/\r\n|\r|\n/).length
      if (limit !== null && count > limit) {
        this.handleImporterError(
          this.$t('tablePasteImporter.limitError', {
            limit,
          })
        )
        return
      }
      this.state = 'parsing'
      await this.$ensureRender()
      this.$papa.parse(this.values.content, {
        delimiter: '\t',
        complete: (parsedResult) => {
          // If parsed successfully and it is not empty then the initial data can be
          // prepared for creating the table. We store the data stringified because it
          // doesn't need to be reactive.

          let data
          let header
          if (this.firstRowHeader) {
            const [rawHeader, ...rest] = parsedResult.data
            data = rest
            header = this.prepareHeader(rawHeader, data)
          } else {
            data = parsedResult.data
            header = this.prepareHeader([], data)
          }
          const getData = () => {
            return new Promise((resolve) => {
              resolve(data)
            })
          }
          this.error = ''
          this.state = null
          const previewData = this.getPreview(header, data)
          this.$emit('getData', getData)
          this.$emit('data', { header, previewData })
        },
        error(error) {
          // Papa parse has resulted in an error which we need to display to the user.
          // All previously loaded data will be removed.
          this.handleImporterError(error.errors[0].message)
        },
      })
    },
  },
}
</script>