import React, { Component } from 'react';
import { Checkbox } from 'antd';
import memoizeOne from 'memoize-one';
import { ScrollSync, Grid, AutoSizer } from 'react-virtualized';
import 'react-virtualized/styles.css';
import _ from 'lodash';
import styles from './Table.less';
import { TableProps, TableState } from './interface';
import Column from './Column';
import Cell from './Cell';

export default class AirTable extends Component<TableProps, TableState> {
    static getDerivedStateFromProps(nextProps: TableProps, prevState: TableState) {
        const { prevProps } = prevState;
        let nextState: TableState = {
            ...prevState,
            prevProps: nextProps,
        };
        if (JSON.stringify(prevProps.dataSource) !== JSON.stringify(nextProps.dataSource)) {
            nextState.dataSource = nextProps.dataSource;
        }
        if (JSON.stringify(prevProps.columns) !== JSON.stringify(nextProps.columns)) {
            nextState.columns = nextProps.columns;
        }
        return nextState;
    }
    constructor(props: TableProps) {
        super(props);
        const { columns, dataSource, tableId } = props;
        this.state = {
            columns,
            dataSource,
            tableId,
            prevProps: props,
            height: document.body.clientHeight - 193,
        };
        this.indexCount = {};
        this.config = {
            overscanColumnCount: 5,
            overscanRowCount: 5,
            columnWidth: 200,
            rowHeight: 40,
        };
        this.memoizeLeftCount = memoizeOne(this.getLeftCount);
        this.memoizeData = memoizeOne(this.filterData);
    }
    //获取左侧固定列数量
    getLeftCount = (columns: []) => {
        let len = 0;
        columns.map((item: any) => {
            item.fixed && len++;
        });
        return len;
    };
    //表头隐藏时过滤数据源
    filterData = (columns: [], dataSource: []) => {
        if (columns.length === 0 || dataSource.length === 0) {
            return [];
        }
        let cloneData = _.cloneDeep(dataSource);
        let i = 0;
        this.indexCount = {};
        cloneData.map((item1: any) => {
            item1.rowData = item1.rowData.filter((item2: any) =>
                columns.some((temp: any) => temp.columnName === item2.colName),
            );
            if (item1.groupId) {
                if (this.indexCount[item1.groupId]) {
                    this.indexCount[item1.groupId].push(item1.id);
                } else {
                    i++;
                    this.indexCount[item1.groupId] = [item1.id];
                }
                item1.index = i;
            }
            return item1;
        });
        return cloneData;
    };
    //下拉加载
    onScrollRow = ({ clientHeight, scrollTop }: any) => {
        const height = clientHeight + scrollTop || 0;
        const { dataSource = [], rowHeight = 40 } = this.state;
        const offset = 100;
        if (dataSource.length === 0) return;
        if (height + offset >= dataSource.length * rowHeight) {
            this.props.onScroll && this.props.onScroll();
        } else return;
    };
    //渲染表头
    renderHeaderCell = ({ columnIndex, key, rowIndex, style }: any) => {
        const { columns } = this.state;
        if (columns.length === 0) return null;
        const { columnType, columnChsName, width } = columns[columnIndex] || {};
        if (columnIndex === 0) {
            return (
                <div key={key} className={styles.leftHeaderCell} style={{ ...style, width: width || 200 }}>
                    <div className={styles.cellNo}>
                        <Checkbox />
                    </div>
                    <div className={styles.cellContent}>
                        <Column type={String(columnType)} title={columnChsName} width={width} />
                    </div>
                </div>
            );
        }
        return (
            <div className={styles.leftHeaderCell} key={key} style={{ ...style, width: width || 200 }}>
                <Column type={String(columnType)} title={columnChsName} width={width} />
            </div>
        );
    };
    //渲染数据
    renderBodyCell = (data: [], { columnIndex, key, rowIndex, style }: any) => {
        const { columns } = this.state;
        if (columns.length === 0 || data.length === 0) {
            return;
        }
        const rowData: any = data[rowIndex] || {};
        const columnData: any = (rowData.rowData && rowData.rowData[columnIndex]) || {};
        const cellData: [] = columnData.cellValueList || [];
        let columnConfig = columns[columnIndex];
        let className = styles.indexCell;

        if (columnIndex === 0) {
            return (
                <div
                    key={key}
                    className={className}
                    style={{
                        ...style,
                    }}
                >
                    <div className={styles.cellContent}>
                        <Cell columns={columns} columnConfig={columnConfig} rowData={rowData} cellData={cellData} />
                    </div>
                </div>
            );
        }
        return (
            <div
                key={key}
                className={className}
                style={{
                    ...style,
                }}
            >
                <div className={styles.cellContent}>
                    <Cell columns={columns} columnConfig={columnConfig} rowData={rowData} cellData={cellData} />
                </div>
            </div>
        );
    };

    render() {
        const { columns, dataSource, checked } = this.state;
        const { overscanColumnCount, overscanRowCount, columnWidth, rowHeight } = this.config;
        let { height } = this.state;
        if (dataSource.length * rowHeight < height) {
            height = dataSource.length * rowHeight;
        }
        //有隐藏列时，修正数据与列头不匹配问题
        const data = this.memoizeData(columns, dataSource);
        //左侧固定列数量
        const leftCount = this.memoizeLeftCount(columns);
        const rowCount = dataSource.length;
        const columnCount = columns.length;
        return (
            <>
                <ScrollSync>
                    {({ onScroll, scrollLeft, scrollTop }: any) => {
                        return (
                            <div className={styles.GridRow}>
                                {
                                    //左侧表头
                                    <div
                                        className={styles.LeftSideGridContainer}
                                        style={{
                                            position: 'absolute',
                                            left: 0,
                                            top: 0,
                                            backgroundColor: `rgba(246, 246, 246, 1)`,
                                            borderLeft: '1px solid #e8e8e8',
                                        }}
                                    >
                                        <Grid
                                            className={styles.HeaderGrid}
                                            columnData={columns}
                                            columnWidth={columnWidth}
                                            columnCount={leftCount}
                                            width={columnWidth * leftCount}
                                            rowHeight={rowHeight}
                                            rowCount={1}
                                            height={rowHeight}
                                            checked={checked}
                                            dataSource={dataSource}
                                            cellRenderer={this.renderHeaderCell}
                                        />
                                    </div>
                                }
                                {
                                    //左侧固定列
                                    <div
                                        className={styles.LeftSideGridContainer}
                                        style={{
                                            position: 'absolute',
                                            left: 0,
                                            top: rowHeight,
                                            borderLeft: '1px solid #e8e8e8',
                                        }}
                                    >
                                        <Grid
                                            className={styles.LeftSideGrid}
                                            overscanRowCount={overscanRowCount}
                                            cellRenderer={this.renderBodyCell.bind(this, data)}
                                            columnWidth={columnWidth}
                                            columnCount={leftCount}
                                            width={columnWidth * leftCount}
                                            rowHeight={rowHeight}
                                            rowCount={rowCount}
                                            height={height}
                                            scrollTop={scrollTop}
                                            checked={checked}
                                            dataSource={dataSource}
                                            columns={columns}
                                        />
                                    </div>
                                }
                                <div className={styles.GridColumn}>
                                    <AutoSizer disableHeight>
                                        {({ width }: any) => (
                                            <div>
                                                {
                                                    //右侧表头
                                                    <div
                                                        style={{
                                                            backgroundColor: `rgba(246, 246, 246, 1)`,
                                                            height: rowHeight,
                                                            width:
                                                                columnWidth * columnCount < width
                                                                    ? columnWidth * columnCount
                                                                    : width, //如果列太少不满一屏时，列头宽度按列计算
                                                        }}
                                                    >
                                                        <Grid
                                                            className={styles.HeaderGrid}
                                                            overscanColumnCount={overscanColumnCount}
                                                            columnData={columns}
                                                            columnWidth={columnWidth}
                                                            columnCount={columnCount}
                                                            width={width}
                                                            rowHeight={rowHeight}
                                                            rowCount={1}
                                                            height={rowHeight}
                                                            scrollLeft={scrollLeft}
                                                            cellRenderer={this.renderHeaderCell}
                                                            checked={checked}
                                                        />
                                                    </div>
                                                }
                                                {
                                                    //右侧内容
                                                    <div
                                                        style={{
                                                            height,
                                                            width,
                                                        }}
                                                    >
                                                        <Grid
                                                            className={styles.BodyGrid}
                                                            overscanColumnCount={overscanColumnCount}
                                                            overscanRowCount={overscanRowCount}
                                                            dataSource={dataSource}
                                                            columnWidth={columnWidth}
                                                            columnCount={columnCount}
                                                            width={width}
                                                            rowHeight={rowHeight}
                                                            rowCount={rowCount}
                                                            height={height}
                                                            onScroll={(...arg: Array<Object>) => {
                                                                onScroll(...arg);
                                                                this.onScrollRow(...arg);
                                                            }}
                                                            cellRenderer={this.renderBodyCell.bind(this, data)}
                                                            columns={columns}
                                                            checked={checked}
                                                        />
                                                    </div>
                                                }
                                            </div>
                                        )}
                                    </AutoSizer>
                                </div>
                            </div>
                        );
                    }}
                </ScrollSync>
            </>
        );
    }
}
