import { useRef } from 'react';
import { useEffect, useMemo, useContext } from 'react';
import './index.less';
import { useHover } from 'ahooks';
import { useState } from 'react';
import { useCallback } from 'react';
import React from 'react';
import { ConfigProvider } from 'antd';
import classNames from 'classnames';

export type TableColumn<T> = {
  title?: string;
  dataIndex: string;
  valueType?: 'option';
  style?: React.CSSProperties;
  render?: (_: any, record: T, index: number) => React.ReactNode;
};

export interface AutoScrollTableProps<T> {
  data: T[];
  columns: TableColumn<T>[]; // 表格数据，必填
  height?: string; // 表格body高度
  width?: string; // 表格宽度
  gridTemplateColumns?: string; // 请参考grid布局
  id?: string;
}

const uuid = `${new Date().getTime()}${Math.random() * 999}table`;

function AutoScrollTable<RecordType>(props: AutoScrollTableProps<RecordType>) {
  const {
    columns,
    data,
    height = '500px',
    width = '100%',
    gridTemplateColumns,
    id = uuid,
  } = props;

  // 为了与 antd 的生态保持兼容性，我们要求必须要使用 `.@{ant-prefix}` 变量来生成类名
  const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
  const prefixCls = getPrefixCls('auto-scroll-table');

  const [timer, setTimer] = useState<any>();
  // 是否显示头部
  const isHeaderShow = useMemo(() => columns.some(value => value.title), [
    columns,
  ]);

  const startScroll = useCallback(() => {
    const box = document.getElementById(id);
    const sTab: any =
      box && box.getElementsByClassName(`${prefixCls}-tabScroll`)[0]; // 要滚动的表

    if (sTab) {
      const tbody = sTab.getElementsByTagName('tbody')[0]; // 要滚动表格的内容
      sTab.appendChild(tbody.cloneNode(true)); // 追加一次滚动内容,以防滚动后可视区域无内容
      const tbdh = tbody.offsetHeight; // 整个表的高度,是因为上边的边不算滚动
      const scrollTop = () => {
        sTab.style.transition = 'top 0.5s linear'; // 过渡动画设为0.5秒
        const t = sTab.offsetTop; // 获取要滚动表的位置
        if (-tbdh >= t) {
          // 比较滚动的距离等于整个表的高度   即第一个表完全看不见
          sTab.style.transition = '0s'; // 过渡动画设为0秒
          sTab.style.top = 0; // 位置设为初始位置
          const time = setTimeout(() => {
            scrollTop();
          }, 0);
          setTimer(time);
        } else {
          sTab.style.top = `${t - tbdh / data.length}px`;
          const time = setTimeout(() => {
            scrollTop();
          }, 3000);
          setTimer(time);
        }
      };
      scrollTop();
    }
  }, [data.length, id]);

  const ref = useRef();
  const isHovering = useHover(ref);
  useEffect(() => {
    if (isHovering) {
      clearTimeout(timer);
    } else {
      startScroll();
    }
  }, [isHovering]);

  // 头部布局
  const headColumnsTemplate = useMemo(() => {
    if (gridTemplateColumns) {
      return gridTemplateColumns;
    }
    if (!isHeaderShow) return '';
    return `repeat(${columns.length}, 1fr)`;
  }, [gridTemplateColumns, isHeaderShow, columns.length]);
  // body布局
  const bodyColumnsTemplate = useMemo(() => {
    if (gridTemplateColumns) {
      return gridTemplateColumns;
    }
    return `repeat(${columns?.length}, 1fr)`;
  }, [columns, gridTemplateColumns]);

  const renderOption = (
    item: TableColumn<RecordType>,
    record: RecordType,
    index: number,
  ) => {
    return item.render && item.render('', record, index);
  };

  const renderItem = (
    item: TableColumn<RecordType>,
    record: RecordType,
    index: number,
  ) => {
    return item.render
      ? item.render(record[item.dataIndex], record, index)
      : record[item.dataIndex];
  };

  return (
    <div id={id}>
      {isHeaderShow && (
        <table className={classNames(`${prefixCls}-top`)} style={{ width }}>
          <thead>
            <tr style={{ gridTemplateColumns: headColumnsTemplate }}>
              {columns.map(h => (
                <th
                  key={h.dataIndex}
                  style={{
                    overflow: 'hidden',
                    textOverflow: 'ellipsis',
                    whiteSpace: 'nowrap',
                  }}
                >
                  {h.title}
                </th>
              ))}
            </tr>
          </thead>
        </table>
      )}
      <div
        className={classNames(`${prefixCls}-scrollBox`)}
        style={{ height, width }}
        ref={ref}
      >
        <table className={classNames(`${prefixCls}-tabScroll`)}>
          <tbody>
            {data?.map((d, dindex) => (
              <tr
                className={classNames(`${prefixCls}-grid`)}
                style={{ gridTemplateColumns: bodyColumnsTemplate }}
                key={dindex}
              >
                {columns.map((i, index) => (
                  <td
                    key={i.dataIndex}
                    style={{
                      overflow: 'hidden',
                      textOverflow: 'ellipsis',
                      whiteSpace: 'nowrap',
                    }}
                    className={classNames(`${prefixCls}-row`)}
                  >
                    {i.style ? (
                      <span style={i.style}>{d[i.dataIndex]}</span>
                    ) : i.valueType === 'option' ? (
                      renderOption(i, d, index)
                    ) : (
                      renderItem(i, d, index)
                    )}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

export { AutoScrollTable };
