<template>
  <div class="n-table" :class="classes">
    <!-- header -->
    <div class="n-table-header">
      <div class="n-table-header-left" :style="headerLeftStyles" v-if="leftColumns.length">
        <n-table-header :columns="leftColumns" :has-resize="hasResize" :class-index="classIndex" @on-sort="onTableSort" @on-resize-end="onResizeEnd"></n-table-header>
      </div>
      <div ref="headerScroll" class="n-table-header-center" :style="headerCenterStyles">
        <n-table-header :columns="mainColumns" :has-resize="hasResize" :class-index="classIndex" @on-sort="onTableSort" @on-resize-end="onResizeEnd"></n-table-header>
      </div>
      <div class="n-table-header-right" :style="headerRightStyles" v-if="rightColumns.length">
        <n-table-header :columns="rightColumns" :has-resize="false" :class-index="classIndex" @on-sort="onTableSort" @on-resize-end="onResizeEnd"></n-table-header>
      </div>
    </div>
    <div class="n-table-main">
      <!-- loading -->
      <n-loading-bar class="n-table-loading" :loading="loading"></n-loading-bar>
      <!-- empty -->
      <n-table-empty v-if="isEmpty" :no-data-builder="noDataBuilder" :style="emptyStyles"></n-table-empty>
      <!-- body -->
      <div class="n-table-body">
        <div ref="bodyScrollLeft" class="n-table-body-left" v-mousewheel="() => $refs.bodyScroll" :style="bodyLeftStyles" v-if="!isEmpty && leftColumns.length">
          <n-table-body :columns="leftColumns" :data-list="dataList" :class-index="classIndex"></n-table-body>
        </div>
        <div ref="bodyScroll" class="n-table-body-center" :style="bodyCenterStyles" @scroll="onBodyScroll">
          <n-table-blank v-if="isEmpty" :columns="mainColumns"></n-table-blank>
          <n-table-body v-else :columns="mainColumns" :data-list="dataList" :class-index="classIndex"></n-table-body>
        </div>
        <div ref="bodyScrollRight" class="n-table-body-right" v-mousewheel="() => $refs.bodyScroll" :style="bodyRightStyles" v-if="!isEmpty && rightColumns.length">
          <n-table-body :columns="rightColumns" :data-list="dataList" :class-index="classIndex"></n-table-body>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import NTableHeader from '_common/table/header'
import NTableBody from '_common/table/body'
import NTableEmpty from '_common/table/empty'
import NTableBlank from '_common/table/blank'
import mousewheel from '@uif/next/lib/directives/mousewheel'
import {updateColumnSort, sortDataList} from '_common/tableUtil'
import {propsArray} from '@uif/next/lib/utils/tools'
import tableCommon from './table-common'
import tableStyles from './table-styles'

export default {
  name: 'n-table',
  mixins: [tableCommon, tableStyles],
  directives: {
    mousewheel
  },
  components: {
    NTableHeader,
    NTableBody,
    NTableEmpty,
    NTableBlank
  },
  props: {
    columns: {
      type: Array,
      default () {
        return []
      }
    },
    dataList: {
      type: Array,
      default () {
        return []
      }
    },
    loading: {
      type: Boolean,
      default: false
    },
    noData: propsArray(['auto', true, false], 'auto'),
    noDataBuilder: {
      type: [Function, String],
      default: ''
    },
    // 列表唯一行样式（下标）
    classIndex: {
      type: Object,
      default () {
        return {}
      }
    },
    hasResize: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
    }
  },
  computed: {
    isEmpty () {
      return this.noData === 'auto' ? (!this.loading && this.dataList.length <= 0) : this.noData
    },
    // 可见列
    visibleColumns () {
      return this.columns.filter(column => !column.h)
    },
    // main 固定列
    mainColumns () {
      return this.visibleColumns.filter(column => !column.fixed)
    },
    // left 固定列
    leftColumns () {
      return this.visibleColumns.filter(column => column.fixed === 'left')
    },
    // right 固定列
    rightColumns () {
      return this.visibleColumns.filter(column => column.fixed === 'right')
    }
  },
  methods: {
    /**
       * 更新尺寸
       * **/
    onBodyScroll (event) {
      const {headerScroll, bodyScrollLeft, bodyScrollRight} = this.$refs
      headerScroll && (headerScroll.scrollLeft = event.target.scrollLeft)
      bodyScrollLeft && (bodyScrollLeft.scrollTop = event.target.scrollTop)
      bodyScrollRight && (bodyScrollRight.scrollTop = event.target.scrollTop)
    },
    /**
     * 滚轮
     * **/
    onMousewheel (event, data) {
      if (Math.abs(data.spinY) > 0) {
        const {bodyScroll} = this.$refs
        if (data.pixelY < 0 && bodyScroll.scrollTop !== 0) {
          event.preventDefault()
        }
        if (data.pixelY > 0 && bodyScroll.scrollHeight - bodyScroll.clientHeight > bodyScroll.scrollTop) {
          event.preventDefault()
        }
        bodyScroll.scrollTop += Math.ceil(data.pixelY / 5)
      }
    },
    /**
       * 排序事件
       * **/
    onTableSort (column) {
      this.columns.forEach(ref => this.$set(ref, '_sort', updateColumnSort(column, ref)))
      sortDataList(this.dataList, column)
      this.$emit('sort', column, column._sort)
    },
    /**
       * 调整列宽
       * **/
    onResizeEnd (column) {
      this.$emit('on-resize-end', column)
    }
  }
}
</script>
