import type { TableProps } from 'antd';
import { Table } from 'antd';
import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer';
import React, { useEffect, useRef, useState } from 'react';
import { VariableSizeGrid as Grid } from 'react-window';

const VirtualTable = <RecordType extends object>(props: TableProps<RecordType> & { tempList: string[], onOneScreen: boolean, height?: number }) => {
  const { columns, scroll, tempList, rowKey, onOneScreen } = props;
  const [tableWidth, setTableWidth] = useState(0);

  const hasWidthColumns = columns!.filter(({ width
  }) => !width)
  const widthColumnCount = hasWidthColumns.length;
  const hasWidthColumnsTotalWidh = columns!.filter(({ width }) => width).reduce((pre, cur) => +(cur?.width || 0) + pre, 0)
  const resetWidth = tableWidth - hasWidthColumnsTotalWidh
  // 所有宽度总和
  const mergedColumns = columns!.map((column) => {

    if (column.width) {
      return {
        ...column,
        // 通过比例计算出这一列应该多大 超过了原始宽度用原来的 否则等比例放大
        width: hasWidthColumnsTotalWidh > tableWidth ? column.width : ((column.width as number) / hasWidthColumnsTotalWidh) * tableWidth
      }
    }
    // 仅在一屏幕展示的情况下调整一下
    if (!onOneScreen) {
      return {
        ...column,
        width: Math.floor(tableWidth / widthColumnCount),
      };
    } else {
      return {
        ...column,
        width: Math.floor(resetWidth / widthColumnCount),
      };
    }
  });
  const gridRef = useRef<any>();
  const [connectObject] = useState<any>(() => {
    const obj = {};
    Object.defineProperty(obj, 'scrollLeft', {
      get: () => {
        if (gridRef.current) {
          return gridRef.current?.state?.scrollLeft;
        }
        return null;
      },
      set: (scrollLeft: number) => {
        if (gridRef.current) {
          gridRef.current.scrollTo({ scrollLeft });
        }
      },
    });

    return obj;
  });

  const resetVirtualGrid = () => {
    gridRef.current?.resetAfterIndices({
      columnIndex: 0,
      shouldForceUpdate: true,
    });
  };

  useEffect(() => resetVirtualGrid, [tableWidth, columns]);

  const renderVirtualList = (rawData: readonly object[], { scrollbarSize, ref, onScroll }: any) => {
    ref.current = connectObject;
    const totalHeight = rawData.length * 42;

    return (
      <Grid
        ref={gridRef}
        className="virtual-grid"
        columnCount={mergedColumns.length}
        columnWidth={(index: number) => {
          const { width } = mergedColumns[index];
          return totalHeight > (scroll?.y as number) && index === mergedColumns.length - 1
            ? (width as number) - scrollbarSize - 1
            : (width as number);
        }}
        height={scroll!.y as number}
        rowCount={rawData.length}
        rowHeight={() => props.height || 42}
        width={tableWidth}
        onScroll={({ scrollLeft }: { scrollLeft: number }) => {
          onScroll({ scrollLeft });
        }}
      >
        {({
          columnIndex,
          rowIndex,
          style
        }: {
          columnIndex: number;
          rowIndex: number;
          style: React.CSSProperties;
        }) => {
          const value = (rawData[rowIndex] as any)[(mergedColumns as any)[columnIndex].dataIndex]
          return (
            <div
              className={classNames('virtual-table-cell', {
                'virtual-table-cell-last': columnIndex === mergedColumns.length - 1,
              })}
              onClick={(e) => {
                e.stopPropagation();
                (columns?.[columnIndex] as any)?.cellClick?.(rawData[rowIndex]);
              }}
              style={{
                ...style,
                boxSizing: 'border-box',
                padding: '7px 10px',
                lineHeight: '28px',
                borderBottom: `1px solid rgba(5, 5, 5, 0.06)`,
                overflow: 'hidden',
                whiteSpace: 'nowrap',
                textOverflow: 'ellipsis',
                background: tempList.includes((rawData[rowIndex])[rowKey as string]) ? '#f7ef9c' : '#fff',
              }}
            >
              {
                columns?.[columnIndex]?.render?.(value, rawData[rowIndex] as any, 0)
                // (typeof (rawData[rowIndex] as any)[(mergedColumns as any)[columnIndex].dataIndex] === 'object') ? '-' :
                //   (rawData[rowIndex] as any)[(mergedColumns as any)[columnIndex].dataIndex]
              }
            </div>
          )
        }
        }
      </Grid>
    );
  };

  return (
    <ResizeObserver
      onResize={({ width }) => {
        setTableWidth(width);
      }}
    >
      <Table
        {...props}
        onRow={props.onRow}
        className="virtual-table"
        columns={mergedColumns}
        pagination={false}
        components={{
          body: renderVirtualList,
        }}
      />
    </ResizeObserver>
  );
};
export default React.memo(VirtualTable);