<template>
  <div :class="{ 'tf-table': true, 'tf-table--no-pagination': !pagination }">
    <el-table
      ref="table"
      v-on="$listeners"
      v-bind="attrs"
      :data="data"
      :span-method="spanMethod"
      :cell-class-name="computedCellClassName"
      v-if="!rerender"
    >
      <template slot="empty">
        <img src="@/assets/icon/null.png" alt="暂无数据" />
      </template>
      <template v-for="{ prop, type, _slot, ...col } of columns">
        <template v-if="_slot">
          <el-table-column :key="prop || type" v-bind="{ headerAlign: 'center', align: 'center', prop, type, ...col }">
            <template v-slot="slotScope" v-if="_slot">
              <slot :name="prop" v-bind="{ ...slotScope, col: { prop, type, _slot, ...col } }" />
            </template>
          </el-table-column>
        </template>
        <el-table-column
          v-else
          :key="prop || type"
          v-bind="{ headerAlign: 'center', align: 'center', prop, type, ...col }"
        />
      </template>
      <slot />
    </el-table>
    <el-pagination
      v-if="pagination && pagination.total > 0"
      class="pagination"
      v-bind="{
        pageSizes: pageSizes,
        total: pagination.total,
        ...pagination,
        currentPage: pagination.currentPage || pagination.current,
        pageSize: pagination.pageSize || pagination.size,
        layout: pagination.layout || 'total, sizes, prev, pager, next, jumper'
      }"
      @size-change="($event) => onPageChange($event, 'size')"
      @current-change="($event) => onPageChange($event, 'current')"
    />
  </div>
</template>

<script lang="ts">
  import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
  import { pageSizes } from '@/utils/constant'
  import { ElTableColumn } from 'element-ui/types/table-column'
  import { ElPagination } from 'element-ui/types/pagination'
  import { cellCallbackParams, ElTable } from 'element-ui/types/table'
  import { camelCase } from 'lodash'

  interface IPagination {
    current?: string | number
    size?: string | number
    total?: string | number
  }

  type ICol = Partial<ElTableColumn> & {
    _slot: boolean
  }
  @Component({ name: 'TfTable', inheritAttrs: false })
  export default class TfTable extends Vue {
    @Prop({ type: Array, default: () => [] }) columns!: ICol[]
    @Prop({ type: Object, default: () => ({}) }) pagination!: ElPagination & IPagination
    @Prop({ type: Array, default: () => [] }) data!: ElTable['data']
    @Prop({ type: Boolean, default: false }) autoHeight!: boolean
    @Prop({ type: [String, Function] }) cellClassName!: ElTable['cellClassName']
    @Prop({ type: [String, Function] }) spanMethod!: (
      param: cellCallbackParams
    ) => [number, number] | { rowspan: number; colspan: number }
    $refs!: { table: ElTable }
    pageSizes = pageSizes
    rerender = false

    mounted() {
      console.log('attrs', this.$attrs)
    }

    get attrs() {
      const defaultAttrs = {
        toolTipEffect: 'light',
        showOverflowTooltip: true,
        size: 'medium',
        rowKey: 'id',
        stripe: true,
        height: '100%'
        // highlightCurrentRow: true
      }
      if (this.autoHeight) delete defaultAttrs.height
      return {
        ...defaultAttrs,
        ...Object.keys(this.$attrs).reduce((acc, key) => {
          acc[camelCase(key)] = this.$attrs[key]
          return acc
        }, {})
      }
    }

    get computedCellClassName() {
      return (param: cellCallbackParams) => {
        let className: string[] = []
        if (this.cellClassName) {
          className.push(typeof this.cellClassName === 'function' ? this.cellClassName(param) : this.cellClassName)
        }
        if (this.spanMethod) {
          const res = this.spanMethod(param)
          const rowspan = !res ? 0 : Array.isArray(res) ? res[0] : res.rowspan
          if (rowspan > 1) {
            className.push('tf-table-merged-span')
            const { index } = param.row as { index: number }
            if (index !== undefined) {
              className.push(index % 2 === 0 ? 'tf-table-merged-span-even' : 'tf-table-merged-span-odd')
            }
            if (this.attrs.stripe) {
              className.push('tf-table-merged-span--striped')
            }
          }
        }

        return className.join(' ')
      }
    }

    onPageChange(e: any, type: 'size' | 'current') {
      this.$emit(`${type}-change`, e)
      this.$emit(`${type}Change`, e)
      this.$emit('page-change', { [type]: e })
      this.$emit('pageChange', { [type]: e })
    }

    doLayout() {
      this.$refs.table.doLayout()
    }

    @Watch('data')
    onDataChange() {
      this.$nextTick(() => {
        this.doLayout()
      })
    }

    @Watch('autoHeight')
    onAutoHeightChange(val) {
      if (val) {
        this.rerender = true
        this.$nextTick(() => {
          this.rerender = false
        })
      }
    }
  }
</script>

<style lang="scss" scoped>
  .tf-table {
    height: 100%;
    min-height: 93px;
    display: flex;
    flex-direction: column;
    position: relative;
    width: 100%;
    padding: $gutter $gutter 0;
    background-color: #fff;
    z-index: 99;
    transition: height 300ms ease;

    >>> .el-table {
      .el-table__header {
        th.el-table__cell {
          height: 40px;
          color: $--color-text-primary;
          background-color: rgba($--color-primary, 0.15);
          padding: 3px 0;
        }
      }
      .el-table__body {
        tr.el-table__row {
          td.el-table__cell {
            height: 34px;
            color: #555;
            background-color: $--color-white;
            padding: 0;
          }
          &.el-table__row--striped {
            td.el-table__cell {
              background-color: rgba($--color-primary, 0.06);
            }
            > a,
            button:not(.el-button--text) {
              color: $--color-white;
            }
          }
          &.current-row {
            td.el-table__cell {
              background-color: rgba($--color-primary, 0.7);
              color: $--color-white;
            }
            &:hover {
              td.el-table__cell {
                color: $--color-warning;
              }
            }
          }
          &.hover-row {
            td.el-table__cell {
              background-color: rgba($--color-primary, 0.1);
              color: $--color-warning;
              > a,
              button {
                color: $--color-warning;
              }
            }
          }
          &:not(.current-row):hover {
            td.el-table__cell {
              background-color: rgba($--color-primary, 0.1);
              color: $--color-warning;
            }
            > a,
            button {
              color: $--color-warning;
            }
          }
        }
      }
      &:not(.el-table--border) {
        .el-table__body tr.el-table__row {
          td.el-table__cell {
            border: 0;
            > a,
            button {
              color: $--color-primary;
            }
          }
          &:last-child {
            td.el-table__cell {
              border-bottom: 1px solid rgba($--color-primary, 0.06);
            }
          }
        }
      }
      .el-table__empty-text {
        img {
          max-width: 154px;
        }
      }
      &__fixed-right {
        box-shadow: none;
      }
      &.el-table--striped .el-table__body tr.el-table__row {
        td.el-table__cell.tf-table-merged-span {
          &--striped {
            &.tf-table-merged-span-even {
              background-color: rgba($--color-primary, 0.06);
            }
            &.tf-table-merged-span-odd {
              background-color: $--color-white;
            }
          }
        }
      }
    }
    .pagination {
      position: relative;
      position: sticky;
      bottom: 0;
      padding: $gutter 0;
      background-color: #fff;
      z-index: 100;
    }
    &--no-pagination {
      padding-bottom: $gutter;
    }
  }
</style>
