<template>
  <table :class="wrapperClass">
    <colgroup>
      <col
        v-for="item in table.currentColumns"
        :key="item.id"
        :width="item.currentWidth"
        :name="item.id"
      />
    </colgroup>

    <thead v-if="showHeader" class="base-table__head">
      <tr
        v-for="headerRowIn in headerRowLen"
        :key="headerRowIn"
        class="table-header-row"
        :class="headerRowIn !== 1 && 'border-top'"
      >
        <template v-if="leftLeafColumns.length">
          <table-th
            v-for="left in leftHeaderRow[headerRowIn - 1]"
            :key="left.id + left.leftWidth"
            fixed="left"
            :item="left"
          ></table-th>
        </template>

        <template v-for="item in headerRow[headerRowIn -1]">
          <!-- eslint-disable -->
          <table-th :item="item" />
        </template>

        <template v-if="rightLeafColumns.length">
          <table-th
            v-for="right in rightHeaderRow[headerRowIn - 1]"
            :key="right.id + right.rightWidth"
            fixed="right"
            :item="right"
          />
        </template>
      </tr>
    </thead>

    <tbody v-if="showBody" class="base-body__content">
      <template v-for="row in curData">
        <tr
          :key="row._uniRowKey"
          :style="{height: table.rowHeight + 'px'}"
          :class="rowClass(row, row.rowIndex)"
          @mouseenter.stop="handleMouseEnter(row.rowIndex)"
          @mouseleave.stop="handleMouseLeave"
          @click="onRowClick($event, row.item, row._uniRowKey, row.rowIndex)"
        >
          <table-td
            v-for="(item, i) in table.currentColumns"
            :key="getKey(item, row)"
            :origin-row="row.item"
            :item="row.cells[item.id]"
            :column="item"
            :first="!i"
            :row-index="row.rowIndex"
            :_uniRowKey="row._uniRowKey"
            :name="getKey(item, row)"
          />
        </tr>
        <!-- eslint-disable -->
        <tr v-if="table.expandable && showExpandRow(row)">
          <td class="table-cell" :colspan="table.currentColumns.length">
            <custom-render
              expand
              :unique-key="row._uniRowKey"
              :row="row.item"
              :r-index="row.rowIndex"
              :custom-render="table.expendRender"
            />
          </td>
        </tr>
      </template>
    </tbody>
  </table>
</template>

<script>
import TableTh from './TableTh'
import TableTd from './TableTd'
import CustomRender from './CustomRender'
import { getHeaderRows } from './util/util'

export default {
  name: 'BaseTable',
  components: { TableTh, TableTd, CustomRender },
  props: {
    showHeader: {
      type: Boolean,
      default: false
    },
    showBody: {
      type: Boolean,
      default: false
    },
    curData: { // eslint-disable-line
      type: Array
    }
  },
  inject: ['table'],
  computed: {
    // 左边固定的叶子列
    leftLeafColumns() {
      return this.table.leftLeafColumns
    },

    // 右边固定的叶子列
    rightLeafColumns() {
      return this.table.rightLeafColumns
    },

    // 头部行数 多级表头时大于1
    headerRowLen() {
      return this.table.headerRows || 1
    },

    // 左侧固定的头
    leftHeaderRow() {
      return getHeaderRows({ columns: this.table.leftColumns })
    },
    // 右侧固定头
    rightHeaderRow() {
      return getHeaderRows({ columns: this.table.rightColumns })
    },
    //
    headerRow() {
      return getHeaderRows({ columns: this.table.curColumns })
    },

    wrapperClass() {
      const { table } = this
      return {
        'base-table': true,
        'border-right': table.border,
        'border-bottom': table.border || !table.stripe
      }
    }
  },
  methods: {
    updateSize(id, size) {
      if (id.includes('column')) {
        this.table.updateColWidth(id, size.offsetWidth)
        return
      }
      this.table.updateRowHeight(id, size.offsetHeight + this.table.rowHeight)
    },
    // 是否展示该行的展开行
    showExpandRow(row) {
      return this.table.expandRows.includes(row._uniRowKey)
    },
    // 判断该元素本身是否绑定了点击事件
    hasOwnClickEvent(target) {
      if (!target) return

      const tagName = target.tagName && target.tagName.toLowerCase() || ''
      if (tagName === 'td') return true

      if (['input', 'button'].includes(tagName) ||
        (target.__vue__ &&
          (!!target.__vue__.bindPopper ||
            target.__vue__.$listeners['click'] ||
            target.__vue__.$listeners['on-click']))
      ) {
        return false
      }
      return this.hasOwnClickEvent(target.parentNode)
    },
    onRowClick(e, originRow, _uniRowKey, rowIndex) {
      // 如果该元素本身上绑定了点击事件 不抛出事件
      if (!this.hasOwnClickEvent(e.target)) return

      this.table.store.commit('setClickRowIndex', rowIndex)
      this.table.store.commit('onExpandStateChange', originRow, _uniRowKey)
    },
    rowClass(row, rowIndex) {
      const { clickRowIndex, hoverRowIndex, showRowClickBg } = this.table
      return [
        'table-row',
        row.rowClass,
        ((clickRowIndex === rowIndex && showRowClickBg) || hoverRowIndex === rowIndex) && 'hover-state',
        this.table.stripe && rowIndex % 2 && 'striped-row'
      ]
    },
    // 生成td的唯一key
    getKey(item, row) {
      return item.id + '_' + row._uniRowKey + (item.leftWidth || '') + (item.rightWidth || '')
    },
    handleMouseEnter(rowIndex) {
      this.table.store.commit('setHoverRowIndex', rowIndex)
    },
    handleMouseLeave() {
      this.table.store.commit('setHoverRowIndex', null)
    }
  }
}
</script>
