<template>
  <div
    class="grid-view__row"
    :class="{
      'grid-view__row--selected': row._.selectedBy.length > 0,
      'grid-view__row--loading': row._.loading,
      'grid-view__row--hover': row._.hover,
      'grid-view__row--warning':
        !row._.matchFilters || !row._.matchSortings || !row._.matchSearch,
    }"
    @mouseover="$emit('row-hover', { row, value: true })"
    @mouseleave="$emit('row-hover', { row, value: false })"
    @contextmenu.prevent="$emit('row-context', { row, event: $event })"
  >
    <template v-if="includeRowDetails">
      <div
        v-if="!row._.matchFilters || !row._.matchSortings || !row._.matchSearch"
        class="grid-view__row-warning"
      >
        <template v-if="!row._.matchFilters">
          Row does not match filters
        </template>
        <template v-else-if="!row._.matchSearch">
          Row does not match search
        </template>
        <template v-else-if="!row._.matchSortings"> Row has moved</template>
      </div>
      <div
        class="grid-view__column"
        :style="{ width: gridViewRowDetailsWidth + 'px' }"
      >
        <div
          class="grid-view__row-info"
          :class="{
            'grid-view__row-info--matches-search':
              row._.matchSearch && row._.fieldSearchMatches.includes('row_id'),
          }"
        >
          <div
            class="grid-view__row-count"
            :class="{ 'grid-view__row-count--small': row.id > 9999 }"
            :title="row.order + ' - ' + row.id"
          >
            {{ row.id }}
          </div>
          <div
            v-if="!readOnly && canDrag"
            class="grid-view__row-drag"
            @mousedown="startDragging($event, row)"
          ></div>
          <a class="grid-view__row-more" @click="$emit('edit-modal', row)">
            <i class="fas fa-expand"></i>
          </a>
        </div>
      </div>
    </template>
    <!--
    Somehow re-declaring all the events instead of using v-on="$listeners" speeds
    everything up because the rows don't need to be updated everytime a new one is
    rendered, which happens a lot when scrolling.
    -->
    <GridViewCell
      v-for="field in fields"
      :key="'row-field-' + row.id + '-' + field.id.toString()"
      :field="field"
      :row="row"
      :state="state"
      :read-only="readOnly"
      :style="{ width: fieldWidths[field.id] + 'px' }"
      @update="$emit('update', $event)"
      @edit="$emit('edit', $event)"
      @select="$emit('select', $event)"
      @unselect="$emit('unselect', $event)"
      @selected="$emit('selected', $event)"
      @unselected="$emit('unselected', $event)"
      @select-next="$emit('select-next', $event)"
    ></GridViewCell>
  </div>
</template>

<script>
import GridViewCell from '@baserow/modules/database/components/view/grid/GridViewCell'
import gridViewHelpers from '@baserow/modules/database/mixins/gridViewHelpers'

export default {
  name: 'GridViewRow',
  components: { GridViewCell },
  mixins: [gridViewHelpers],
  props: {
    row: {
      type: Object,
      required: true,
    },
    fields: {
      type: Array,
      required: true,
    },
    fieldWidths: {
      type: Object,
      required: true,
    },
    includeRowDetails: {
      type: Boolean,
      required: false,
      default: () => false,
    },
    readOnly: {
      type: Boolean,
      required: true,
    },
    canDrag: {
      type: Boolean,
      required: true,
    },
  },
  data() {
    return {
      // The state can be used by functional components to make changes to the dom.
      // This is for example used by the functional file field component to enable the
      // drop effect without having the cell selected.
      state: {},
      // A list containing field id's of field cells that must not be converted to the
      // functional component even though the user has selected another cell. This is
      // for example used by the file field to finish the uploading task if the user
      // has selected another cell while uploading.
      alive: [],
    }
  },
  methods: {
    isCellSelected(fieldId) {
      return this.row._.selected && this.row._.selectedFieldId === fieldId
    },
    selectCell(fieldId, rowId = this.row.id) {
      this.$store.dispatch(this.storePrefix + 'view/grid/setSelectedCell', {
        rowId,
        fieldId,
      })
    },
    setState(value) {
      this.state = value
    },
    addKeepAlive(fieldId) {
      if (!this.alive.includes(fieldId)) {
        this.alive.push(fieldId)
      }
    },
    removeKeepAlive(fieldId) {
      const index = this.alive.findIndex((id) => id === fieldId)
      if (index > -1) {
        this.alive.splice(index, 1)
      }
    },
    startDragging(event, row) {
      if (this.readOnly) {
        return
      }

      event.preventDefault()
      this.$emit('row-dragging', { row, event })
    },
  },
}
</script>