import { getPrimaryOrFirstField } from '@baserow/modules/database/utils/field'
import BigNumber from 'bignumber.js'

export default {
  data() {
    return {
      // If true, then the user must choose which values will be deleted. This only
      // happens if field.link_row_multiple_relationships == false, meaning that only
      // one relationship can persist.
      removingRelationships: false,
      removingRelationShipIds: [],
    }
  },
  computed: {
    /**
     * Returns the value of the field that can be used when creating a new row
     * in the linked table starting from the current row.
     */
    presetsForNewRowInLinkedTable() {
      const presets = {}
      const value = this.primaryFieldLinkRowValue
      if (value) {
        presets[`field_${this.field.link_row_related_field_id}`] = [value]
      }
      return presets
    },
    /**
     * Returns the value of the field.
     */
    primaryFieldLinkRowValue() {
      // Set the starting row as preset so that can be used later if the user wants to create a new row
      // starting from the selected row.
      if (!this.allFieldsInTable) {
        return
      }
      const primaryField = getPrimaryOrFirstField(this.allFieldsInTable)
      const primaryFieldType = this.$registry.get(
        'field',
        primaryField._.type.type
      )
      return {
        id: this.row.id,
        value: primaryFieldType.toHumanReadableString(
          primaryField,
          this.row[`field_${primaryField.id}`]
        ),
      }
    },
    visibleValues() {
      if (this.removingRelationships) {
        return this.value.filter(
          (v) => !this.removingRelationShipIds.includes(v.id)
        )
      } else {
        return this.value
      }
    },
    canAddValue() {
      return (
        this.field.link_row_multiple_relationships ||
        (Array.isArray(this.value) && this.value.length < 1)
      )
    },
  },
  methods: {
    /**
     * Removes an existing relation from the value.
     */
    removeValue(event, value, id) {
      // If the cell is in delete relationships mode, then the newly deleted
      // relationship must be added to the list of to be deleted items.
      if (this.removingRelationships) {
        this.removingRelationShipIds.push(id)
        // The backend only accepts one value in that case, so if one is left, then
        // the value is actually updated.
        if (this.removingRelationShipIds.length + 1 === value.length) {
          const newValue = JSON.parse(JSON.stringify(value)).filter(
            (v) => !this.removingRelationShipIds.includes(v.id)
          )
          this.removingRelationships = false
          this.removingRelationShipIds = []
          this.$emit('update', newValue, value)
        }
        return
      }

      // If it's not allowed to have multiple relationships, then the backend will
      // accept only one value during update. Because it will otherwise fail, the cell
      // is put in a mode where the user must delete all relationships except one.
      if (!this.field.link_row_multiple_relationships && value.length > 2) {
        this.removingRelationships = true
        this.removingRelationShipIds = [id]
        return
      }

      const newValue = JSON.parse(JSON.stringify(value))
      const index = newValue.findIndex((item) => item.id === id)
      if (index === -1) {
        return
      }

      newValue.splice(index, 1)
      this.$emit('update', newValue, value)
    },
    /**
     * Adds a new relation to the value. This typically happens via the modal.
     */
    addValue(value, { row, primary }) {
      // Check if the relation already exists.
      for (let i = 0; i < value.length; i++) {
        if (value[i].id === row.id) {
          return
        }
      }

      // Prepare the new value with all the relations and emit that value to the
      // parent.
      const rowValue = this.$registry
        .get('field', primary.type)
        .toHumanReadableString(primary, row[`field_${primary.id}`])

      const newValue = JSON.parse(JSON.stringify(value))
      newValue.push({ id: row.id, value: rowValue, order: row.order })
      // Match the backend order sorting
      newValue.sort((a, b) => {
        const orderA = new BigNumber(a.order)
        const orderB = new BigNumber(b.order)
        return orderA.isLessThan(orderB)
          ? -1
          : orderA.isEqualTo(orderB)
          ? a.id - b.id
          : 1
      })
      this.$emit('update', newValue, value)
    },
  },
}