<template>
  <div class="bio-table">
    <slot :loading="loading" :search="searchHandler" name="form"/>

    <slot/>

    <div id="bio-table-p" ref="bioTableP" class="bio-table-p">
      <el-table
        v-if="!reLoadTable"
        ref="table" v-loading.lock="loading" :border="border"
        :cell-class-name="cellClassName" :current-row-key="currentRowKey"
        :data="tableData" :default-expand-all="defaultExpandAll" :default-sort="defaultSort" :empty-text="emptyText"
        :expand-row-keys="expandRowKeys" :fit="fit"
        :height="tableMaxHeight || height" :highlight-current-row="highlightCurrentRow" :max-height="maxHeight"
        :row-class-name="rowClassName" :row-key="rowKey"
        :row-style="rowStyle" :show-header="showHeader" :show-summary="showSummary"
        :size="size" :span-method="spanMethod" :stripe="stripe"
        :sum-text="sumText" :summary-method="summaryMethod" :tooltip-effect="tooltipEffect || 'light'"
        style="width: 100%;"
        v-on="$listeners" @sort-change="sortChange">
        <el-table-column
          v-if="useIndex"
          :fixed="indexFixed"
          :index="indexMethod"
          :width="indexWidth"
          align="center"
          label="#"
          type="index">
        </el-table-column>

        <slot name="prepend"/>

        <bioColumn
          v-for="(column, columnIndex) in columnsUse"
          :key="columnIndex"
          :column="column"
          :columnIndex="columnIndex">
          <template slot="perSlot" slot-scope="scope">
            <slot :$index="scope.$index" :columnProp="column.prop" :name="scope.soltName" :row="scope.row"></slot>
          </template>
        </bioColumn>

        <slot name="append"/>

        <el-table-column v-if="appendAmpty" width="40"></el-table-column>

        <template #empty>
          <template v-if="!loading">
            <bio-icon name="nodata"/>
            <div class="empty-text">{{ t('bio.public.noData') }}</div>
          </template>

          <template v-else>
            <span> </span>
          </template>
        </template>
      </el-table>
    </div>

    <div v-if="showPaginationFlag" class="mt-10 text-right">
      <el-pagination
        v-if="paginationSmall"
        :hide-on-single-page="hideOnSinglePage"
        :page-size="pagination.pageSize"
        :total="total"
        background
        layout="total, prev, pager, next"
        small
        @current-change="handleCurrentChange">
      </el-pagination>

      <el-pagination
        v-else
        :current-page="pagination.currentPage"
        :hide-on-single-page="hideOnSinglePage"
        :layout="paginationLayout"
        :page-size="pagination.pageSize"
        :page-sizes="pageSizes"
        :total="total"
        background
        small
        @next-click="handleCurrentChange"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        @prev-click="handleCurrentChange">
      </el-pagination>
    </div>
  </div>
</template>

<script>
import Vue from 'vue';
import {throttle} from 'throttle-debounce';
import props from './props';
import bioColumn from './column';
import {setSessionStorage} from '../../../src/utils/bioknow/utils';
import http from '../../../src/utils/bioknow/http';
import Locale from 'element-ui/src/mixins/locale';

export default {
  name: 'BioTable',
  props,
  components: {
    bioColumn
  },
  mixins: [Locale],

  data() {
    return {
      Vue,
      pagination: {
        // pageSize: ~~this.$getSessionStorage('pageSize') || this.pageSize,
        pageSize: this.pageSize,
        currentPage: this.currentPage
      },
      loading: false,
      tableData: [],
      total: 0,
      cacheLocalData: [],
      sortParams: null,
      tableMaxHeight: null,
      reLoadTable: false,
      columnsRefreshUse: false,
      columnsUse: [],
      showPaginationFlag: this.showPagination // 根据数据总页数是否大于1来判断是否显示页码
    };
  },

  computed: {
    appendAmpty() {
      return this.columnsUse &&
        this.columnsUse.length &&
        this.columnsUse[this.columnsUse.length - 1].align &&
        this.columnsUse[this.columnsUse.length - 1].align === 'right';
    },

    indexWidth() {
      let width = 40;

      if (this.total) {
        width = (this.total + '').length * 8 + 15;
      }

      return width;
    }
  },

  watch: {
    columnsRefresh: {
      immediate: true,
      handler(e) {
        this.columnsRefreshUse = e;
      }
    },
    columns: {
      immediate: true,
      handler(e) {
        this.columnsUse = e;
      }
    }
  },

  methods: {
    isFunction(fn) {
      return Object.prototype.toString.call(fn) === '[object Function]';
    },

    indexMethod(index) {
      if (this.pagination.currentPage === 1) {
        return index + 1;
      } else {
        return this.pagination.pageSize * (this.pagination.currentPage - 1) + index + 1;
      }
    },

    sortChange(columns) {
      const {column, prop, order} = columns;
      this.sortParams = null;
      this.columnsRefreshUse = false;
      if (order) {
        this.sortParams = {
          asc: order === 'ascending',
          // orderByField: _.kebabCase(prop).replace(/-/g, '_'),
          orderByField: prop,
          sorttid: column.level === 1 && this.columnsUse[column.index].tid || undefined,
          innerid: column.level === 1 && this.columnsUse[column.index].innerid || undefined
        };
      } else {
        this.sortParams = {
          asc: undefined,
          orderByField: undefined,
          sorttid: undefined
        };
      }

      this.dataChangeHandler();
    },

    handleSizeChange(pageSize) {
      this.pagination.pageSize = pageSize;
      setSessionStorage('pageSize', pageSize);
      this.dataChangeHandler({resetPage: true});
    },

    handleCurrentChange(currentPage) {
      this.pagination.currentPage = currentPage;
      this.dataChangeHandler();
    },

    searchHandler() {
      this.sortParams = {};
      this.pagination.currentPage = 1;
      this.dataChangeHandler({...arguments[0], resetPage: true});
    },

    clearSort() {
      this.$refs.table.clearSort();
    },

    dataChangeHandler() {
      const {type} = this;
      if (type === 'local') {
        this.$refs.table.clearSort();
        this.localHandler(arguments[0]);
      } else if (type === 'remote') {
        this.remoteHandler(arguments[0]);
      }
    },

    dataFilter(data) {
      const {currentPage, pageSize} = this.pagination;
      if (this.showPagination) {
        return data.filter((v, i) => i >= (currentPage - 1) * pageSize && i < currentPage * pageSize);
      } else {
        return data;
      }
    },

    localHandler() {
      const {cacheLocalData} = this;
      this.total = cacheLocalData.length;
      this.tableData = this.dataFilter(cacheLocalData);
    },

    remoteHandler(customParams = {}, isMounted = false) {
      this.loading = true;

      // 只有在 mounted 的时候才执行columnsMethod方法
      if (isMounted || this.columnsRefreshUse) this.reLoadTable = true;

      // 切换pageSize的时候需要将table重新load，不然高度计算有问题
      if (this.setMaxHeight && customParams.resetPage) this.reLoadTable = true;

      let {
        method, url, currentPageKey, pageSizeKey, params, sortParams,
        showPagination, pagination
      } = this;

      let params_ = {...params, ...sortParams, ...customParams};

      if (showPagination) {
        Object.assign(params_, {
          [currentPageKey]: params_.resetPage ? 1 : pagination.currentPage,
          [pageSizeKey]: pagination.pageSize
        });
      }

      let requestObject;

      if (method.toLowerCase() === 'get') {
        requestObject = http.get(url, params_);
      } else {
        requestObject = http.post(url, params_);
      }

      requestObject.then(({data, msg}) => {
        if (data) {
          // table加载前执行
          if (this.beforeLoad && this.isFunction(this.beforeLoad)) this.beforeLoad(data);

          // 设置 columns
          // if (this.columnsRefreshUse && !isMounted) console.log('重置表头');

          if (isMounted || this.columnsRefreshUse) {
            if (this.columnsMethod && this.isFunction(this.columnsMethod)) {
              this.columnsMethod(data);
            } else if (!this.columns.length) {
              this.columnsUse = data && data.columns ? data.columns : [];
            }

            this.reLoadTable = false;
          }

          if (data && data.list) {
            this.tableData = this.dataHandler ? this.dataHandler(data.list) : data.list;
            this.total = data.total;
          } else {
            this.tableData = [];
            this.sortParams = {};
            this.total = 0;
          }

          // table加载后执行
          if (this.afterLoad && this.isFunction(this.afterLoad)) {
            this.afterLoad({
              tableData: this.tableData,
              total: this.total,
              allData: data,
              pageNum: data.pageNum || this.pagination.currentPage, // 当前页码
              params: data.params,
              formid: data.formid,
              msg
            });
          }

          if (params_.resetPage) {
            this.pagination.currentPage = 1;
            this.reLoadTable = false;
            this.$refs.table.clearSort();
          }

          // 每次table 加载完成都重新赋值table的高
          if (this.setMaxHeight) this.resizeTableHeight();
        }
        this.loading = false;
      }).catch(() => {
        this.loading = false;
      });
    },

    loadLocalData(data) {
      if (!data) throw new Error('When the type is \'local\', you must set attribute \'data\' and \'data\' must be a array.');

      let cacheData = this.deepCopy ? JSON.parse(JSON.stringify(data)) : data;

      this.tableData = this.dataFilter(cacheData);
      this.cacheLocalData = cacheData;
      this.total = cacheData.length;
    },

    resizeTableHeight: throttle(300, false, function() {
      this.tableMaxHeight = this.$refs.bioTableP.offsetHeight;
    })
  },

  mounted() {
    const bioTableP = this.$refs.bioTableP;

    if (this.setMaxHeight && bioTableP) {
      this.$nextTick(() => {
        this.tableMaxHeight = bioTableP.offsetHeight;
        window.addEventListener(
          'resize',
          this.resizeTableHeight,
          false
        );
      });
    }

    const {type, data, defaultSort} = this;
    if (type === 'remote') {
      if (defaultSort) {
        return false;
      } else {
        this.remoteHandler({}, true);
      }
    } else if (type === 'local') {
      this.loadLocalData(data);
      this.$watch('data', function(val) {
        this.loadLocalData(val);
      }, {
        deep: true
      });
    }
  },

  beforeDestroy() {
    window.removeEventListener('resize', this.resizeTableHeight);
  }
};
</script>
<style lang="scss">
.bio-table-p {
  flex: 1 1 auto; //兼容Ie 注意ie下flex: 1被解析为flex: 1 1 0
  flex-grow: 1;
  overflow: hidden;
}

.bio-table {
  display: flex;
  flex-direction: column;

  & > .el-form {
    .el-form-item__content {
      max-width: 150px;
      @media (max-width: 1400px) {
        max-width: 120px;
      }
    }
  }
}
</style>
