import React from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import Page from '../../page/lib/Page';
import Table from './Table';
import StatusBox from '../../statusbox/lib/Statusbox';
// @require '../style/data_table.scss'

/**
 * 已经废弃请使用AutoTable替换
 * 数据表格组件，封装至Table 具有以下功能：
 * 自动分页
 * 数据缓存
 * 选中
 * 排序
 */
class DataTable extends React.Component {

  static propTypes = {
    style: PropTypes.object,
    className: PropTypes.string,
    // ////////////////////// Table //////////////////////
    /**
     * 配置每列表头
     */
    cols: PropTypes.arrayOf(PropTypes.shape({
      /**
       * 表格头部一列名称
       */
      display: PropTypes.any.isRequired,
      /**
       * 表格一列所占宽度百分比
       */
      width: PropTypes.number,
      /**
       * 跨列
       * 默认为1
       */
      colspan: PropTypes.number,
    })).isRequired,
    /**
     * @transformable
     * 表格体的数据
     * 二维数组 如果数组元素是
     * React组件实例：展示元素本身
     * else：展示元素toString()
     * 如果数组元素是空字符串或者==null会显示为'-'
     * 当data==null时会显示正在加载在中
     */
    data: PropTypes.arrayOf(PropTypes.array),
    /**
     * 是否可以选择行，可以的话会在左边显示checkbox来供选择
     */
    canSelect: PropTypes.bool,
    /**
     * 但被选中但行发生变化时回调
     * onSelectedChange(rowsSelected) 当前被选中的[row]
     */
    onSelectedChange: PropTypes.func,
    /**
     * 当其中一行被onClick是回调 callback(data[i])
     */
    onRowClick: PropTypes.func,
    /**
     * 给相邻两行设置不同的背景颜色，做视觉区分
     */
    differentiateRow: PropTypes.bool,
    /**
     * 悬浮展示在表格的正中间
     */
    overlap: PropTypes.any,
    /**
     * 当没有数据时显示
     */
    noDataMsg: PropTypes.any,
    // ////////////////////// DataTable //////////////////////
    /**
     * @transformable
     * 是否显示正在加载中
     */
    loading: PropTypes.bool,
    /**
     * 正在加载中时的显示
     */
    loadingDisplay: PropTypes.any,
    /**
     * 是否开启分页功能，默认开启
     * 如果开启会在 data.length > maxRow 时在底部显示分页组件，用户点击分页组件切换页面时会自动显示对应的数据
     */
    canPage: PropTypes.bool,
    /**
     * 这些数据的总行数，当totalRow>maxRow时会显示分页组件
     * 分页组件的最大页数跟进totalRow和maxRow来确定
     * 如果totalRow没有被赋值，默认等于data.length
     */
    totalRow: PropTypes.number,
    /**
     * 当data.length小于当前用户正处于的页数需要的数据时会调用通知去加载更多的数据
     * 在更多的数据被加载前会先显示加载中
     * onNeedMoreData(currentPage, maxRow);
     * currentPage从0开始计数
     */
    onNeedMoreData: PropTypes.func,
    /**
     * 一页里最大显示行数，如果要显示的行数超过max就在底部显示出分页组件
     */
    maxRow: PropTypes.number,
    /**
     * 当用户点击分页按钮切换时回调
     * onPageChange(page);
     * 从0开始计数
     */
    onPageChange: PropTypes.func,
    /**
     * 是否缓存数据。
     * 如果开启缓存已经加载过的数据就不会再触发onNeedMoreData去询问更多数据
     * 如果没有开启就会在每次切换页面时触发onNeedMoreData去询问更多数据
     * 默认开启
     */
    cache: PropTypes.bool,
  };

  static defaultProps = {
    canSelect: Table.defaultProps.canSelect,
    differentiateRow: Table.defaultProps.differentiateRow,
    noDataMsg: Table.defaultProps.noDataMsg,
    maxRow: 5,
    loading: false,
    canPage: true,
    loadingDisplay: <StatusBox type="loading" size="l">加载中</StatusBox>,
    cache: true,
  };

  state = {
    /**
     * 是否显示正在加载中
     */
    loading: false,
    /**
     * 当前要展示在table里的rows
     */
    visibleRowList: [],
    /**
     * 当前选中页
     */
    currentPage: 0,
  };

  constructor(props) {
    super(props);
    this.handleProps(this.props, false);
  }

  componentWillReceiveProps(nextProps) {
    this.handleProps(nextProps, true);
  }

  handleProps = (props, hasMounted) => {
    const { maxRow, canPage, data, loading } = props;
    const { currentPage } = this.state;
    // 如果要显示选择 默认是全不选中
    if (data != null) {
      // 要显示出的rows
      let startIndex = currentPage * maxRow;
      let endIndex = startIndex + maxRow;
      let visibleRowList = data;
      if (canPage) {
        visibleRowList = data.slice(startIndex, endIndex);
      }
      if (hasMounted) {
        this.setState({
          visibleRowList,
          loading,
        });
      } else {
        this.state.visibleRowList = visibleRowList;
        this.state.loading = loading;
      }
    } else {
      if (hasMounted) {
        this.setState({
          loading: true,
        });
      } else {
        this.state.loading = true;
      }
    }
  };

  /**
   * 跳转到第page页，
   * 如果没有第page页的数据会回调onNeedMoreData去加载更多的数据
   * 会回调onPageChange通知页面变化
   * @param page 跳转到第page页，从0开始计数
   */
  goPage = (page) => {
    let { onPageChange, data, maxRow, onNeedMoreData, cache } = this.props;
    let startIndex = page * maxRow;
    // 1. 或者中间数据为空时
    // 2. 没有足够的数据去显示时
    if (data[startIndex] == null || startIndex >= data.length) {
      // 通知去加载更多的数据,显示正在加载中
      if (typeof onNeedMoreData === 'function') {
        onNeedMoreData(page, maxRow);
      }
      this.setState({
        loading: true,
        currentPage: page,
        isSelectAll: false,
      });
    } else {
      // 有数据可以显示
      let endIndex = startIndex + maxRow;
      let visibleRowList = data.slice(startIndex, endIndex);
      // 如果关闭缓存就去通知onNeedMoreData
      if (!cache && typeof onNeedMoreData === 'function') {
        onNeedMoreData(page, maxRow);
      }
      this.setState({
        // 关闭缓存的时候需要显示loading
        loading: !cache,
        visibleRowList,
        currentPage: page,
        isSelectAll: false,
      });
    }
    if (onPageChange) {
      onPageChange(page);
    }
  };

  /**
   * 只显示第page页，没有任何附加操作
   * @param page 显示第page页，从0开始计数
   */
  showPage = (page) => {
    this.setState({
      currentPage: page,
    });
  };

  /**
   * 选中或者不选中事件发生时通知
   */
  notifySelectedChange = () => {
    const { onSelectedChange, data } = this.props;
    if (onSelectedChange != null) {
      let selectedRows = [];
      data.forEach((row, index) => {
        if (row.selected) {
          row.index = index;
          selectedRows.push(row);
        }
      });
      onSelectedChange(selectedRows);
    }
  };

  /**
   * 设置选中或者不选中全部
   * @param selected
   */
  applySelectAll = (selected) => {
    const { data } = this.props;
    data.forEach((row) => {
      row.selected = selected;
    });
    this.forceUpdate();
  };

  render() {
    let {
      cols, data, canSelect, onRowClick, differentiateRow, overlap, noDataMsg,
      maxRow, canPage, totalRow, loadingDisplay,
      className, style,
    } = this.props;
    let { currentPage, visibleRowList, loading } = this.state;
    if ((totalRow == null || totalRow === 0) && data != null) {
      totalRow = data.length;
    }
    // 是否显示分页
    let showPager = false;
    // 分页总页数
    let totalPage = 0;
    if (data != null && canPage) {
      // 是否显示分页组件
      showPager = totalRow > maxRow;
      // 要显示出的rows
      // 当rows数量大于maxRow时采用分页时的总页数
      totalPage = Math.ceil(totalRow / maxRow);
    }
    return (
      <div className={classnames('im-data-table', className)} style={style}>
        <Table
          overlap={loading ? loadingDisplay : overlap}
          cols={cols}
          onRowClick={onRowClick}
          differentiateRow={differentiateRow}
          noDataMsg={noDataMsg}
          data={visibleRowList}
          canSelect={canSelect}
          onSelectedChange={this.notifySelectedChange}
        />
        {showPager ?
          <Page
            size="s"
            totalPage={totalPage}
            page={currentPage}
            onChange={this.goPage}
          /> : null}
      </div>
    );
  }
}

export default DataTable;
