import React, { useState, useEffect, useMemo, useRef, useImperativeHandle, forwardRef } from 'react';
import { Tooltip } from 'antd';
import { AutoSizer, InfiniteLoader, List } from 'react-virtualized';
import IconFont from '../../../themeComponents/IconFont';
import Box from '../../../themeComponents/CBox';
import { debounce, cloneDeep } from 'lodash';
import { computedCuurentGrid, arraySliceForX, simpleGrid } from './utils';
import { concat } from 'lodash';
import './index.less';
import { useSize } from 'ahooks';

const ScrollList = forwardRef(function InfiniteScrollLayout(props, ref) {
  const { data, itemGrid, itemHeight, threshold, isNoData, className = '', toppingConfig, hasLoadPrev, loadPrev, prethreshold } = props;
  const infiniteRef = useRef(null);
  const loadingRef = useRef(false);
  const scrollRef = useRef(false);
  const toppingRef = useRef(false);
  const scrollbarWidth = getScrollbarWidth()
  const [showBackTop, setShowBackUp] = useState(false);
  const [topping, setTopping] = useState(false);
  const [currentGrid, setContentGrid] = useState(computedCuurentGrid());
  let debounced = null;

  useEffect(() => {
    const bindResizeEvent = () => {
      setContentGrid(computedCuurentGrid());
    };

    window.addEventListener('resize', bindResizeEvent, false);

    return () => {
      debounced && debounced.cancel();
      window.removeEventListener('resize', bindResizeEvent, false);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  const { toppingHeight, headerHeight, headerComponent, toppingComponent } = toppingConfig
  const rowCount = useMemo(() => Math.floor(24 / itemGrid[currentGrid]), [itemGrid, currentGrid]);
  const renderData = useMemo(() => {
    let arr = arraySliceForX(data, rowCount)
    arr = concat([[], [], []], arr) //前3行渲染做特殊处理
    return arr
  }, [data, rowCount]);

  function forceUpdateGrid() {
    infiniteRef.current && infiniteRef.current._registeredChild.forceUpdateGrid();
  }

  function scrollToPosition(...args) {
    infiniteRef.current && infiniteRef.current._registeredChild.scrollToPosition(...args);
  }

  function scrollToRow(...args) {
    infiniteRef.current && infiniteRef.current._registeredChild.scrollToRow(...args);
  }

  useImperativeHandle(ref, () => ({ forceUpdateGrid, scrollToRow, scrollToPosition }));

  const loadMore = async () => {
    if (props.hasLoadMore && props.loadMore && !loadingRef.current) {
      loadingRef.current = true;
      await props.loadMore();
      loadingRef.current = false;
    }
  };
  function onListScroll(options) {
    if (options.scrollTop >= headerHeight) {
      setTopping(true)
    } else {
      setTopping(false)

    }
    if (hasLoadPrev && !loadingRef.current && loadPrev && options.scrollTop === 0 && scrollRef.current) {
      loadingRef.current = true;
      loadPrev().then(dataLength => {
        if (dataLength) {
          const row = Math.ceil(dataLength / rowCount);
          if (row > 0) {
            scrollToPosition(row * itemHeight);
          }
        }
        loadingRef.current = false;
      });
    }

    if (!scrollRef.current && options.scrollTop >= prethreshold) {
      scrollRef.current = true;
    }
    debounced && debounced.cancel();
    debounced = debounce(() => {
      const flag = options.scrollTop > 200;
      if (showBackTop !== flag) {
        setShowBackUp(flag);
      }
      props.onScroll && props.onScroll(options);
    }, 100);
    debounced();
  }
  function getScrollbarWidth() {
    let scrollDiv = document.createElement('div');
    scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'
    document.body.appendChild(scrollDiv)
    let scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
    document.body.removeChild(scrollDiv)
    return scrollbarWidth
  }

  function rowRender({ key, index, style }) {
    const { gutter, paddingRow, rowClass, hasLoadMore, itemClass } = props;
    let rowData = renderData[index] || [];
    let len = rowCount - rowData.length;
    if (rowData.length < rowCount) {
      for (let i = 0; i < len; i++) {
        rowData.push(null);
      }
    }
    return (
      <div key={key} style={{ ...style, padding: `0 ${paddingRow}` }} className={`row-group-part  ${rowClass}`}>
        {rowData?.length && rowData.map((v, i) => (
          <div
            key={`${key}-${i}`}
            className={`row-item-part ${v === null && hasLoadMore ? 'row-item-placeholder' : ''} ${v !== null ? itemClass : ''}`}
            style={{
              width: `${(100 / 24) * itemGrid[currentGrid]}%`,
              height: itemHeight,
              marginRight: gutter,
              paddingBottom: gutter
            }}
          >
            {v && props.renderItem(v, i)}
          </div>
        ))}
      </div>
    );
  }
  const size = useSize(toppingRef.current && toppingRef.current?.querySelector('.ReactVirtualized__Grid__innerScrollContainer'))
  const boxSize = useSize(toppingRef.current)

  const hasScrollbar = useMemo( () => boxSize?.width - size?.width!==0 ,[boxSize?.width, size?.width])

  function _isRowLoaded({ index }) {
    return !!renderData[index];
  }
  
  const boxWidth = useMemo(() => hasScrollbar? `calc(100% - ${scrollbarWidth}px)`:'100%',[hasScrollbar,scrollbarWidth])
  console.log(boxWidth);
  return (

    <Box boxRef={toppingRef} className={`lm-c-top-scroll-layout  ${className}`} >
      <div style={{ width: boxWidth }} className="topping-scroll-tip"></div>
      {topping ? <><div style={{ width: boxWidth, height: toppingHeight, top: 0, zIndex: 22, boxShadow: topping ? '0px 5px 14px rgba(0, 0, 0, 0.05)' : 'none' }} className='list-topping-box'>{toppingComponent}</div><div style={{ width: boxWidth }} className="topping-scroll-tip-mask"></div> </> : ''}

      <InfiniteLoader isRowLoaded={_isRowLoaded} loadMoreRows={loadMore} rowCount={renderData.length + 1} ref={infiniteRef} threshold={threshold}>
        {({ onRowsRendered, registerChild }) => {
          return (
            <AutoSizer>
              {({ width, height }) => {
                return (
                  <List
                    width={width}
                    onRowsRendered={onRowsRendered}
                    ref={registerChild}
                    height={headerHeight + toppingHeight >= height ? headerHeight + toppingHeight : height - 20}
                    rowCount={renderData.length}
                    rowHeight={(item) => {
                      if (toppingConfig) {
                        if (item.index === 0) {
                          return headerHeight || 0
                        }
                        if (item.index === 1) {
                          return toppingHeight || 0
                        }
                        if (item.index === 2) {
                          return 0
                        }

                      }
                      return itemHeight
                    }}
                    rowRenderer={(item) => {
                      if (toppingConfig) {
                        if (item.index === 0) {
                          return headerComponent
                        }
                        if (item.index === 1) {
                          return <div style={{ height: toppingHeight, opacity: topping ? 0 : 1 }} className={` list-topping-box`}>{toppingComponent}</div>
                        }
                        if (item.index === 2) {
                          return isNoData ? <div className="topping-scroll-nodata-view" style={{ height: `calc(100% - ${headerHeight + toppingHeight}px)`, top: `${headerHeight + toppingHeight}px`, backgroundPosition: `center ${100}px` }}></div> : topping ? null : <div style={{ top: headerHeight, height }} className='topping-scroll-tip-inner'></div>
                        }
                      }
                      return rowRender(item)
                    }}
                    onScroll={onListScroll}
                  />
                )
              }}
            </AutoSizer>
          );
        }}
      </InfiniteLoader>

      {props.hasBackTop && showBackTop && (
        <Tooltip title="返回顶部" placement="top">
          <div className="scoll-back-top" onClick={() => scrollToPosition(0)}>
            <IconFont type="icon-a-zhiding3" />
          </div>
        </Tooltip>
      )}
    </Box>
  );
});

ScrollList.defaultProps = {
  itemHeight: 200,
  gutter: 20,
  itemGrid: cloneDeep(simpleGrid),
  hasLoadMore: true,
  hasLoadPrev: true,
  threshold: 5,
  prethreshold: 200,
  hasBackTop: false,
  data: []
};

export default ScrollList;
