/**
 * Created by jiangzhixiong
 */

import React, { forwardRef, ReactNode, useContext, useEffect, useImperativeHandle, useRef } from 'react'
import { ConfigProvider } from '@zhst/meta';
import classNames from 'classnames';
import InfiniteScroll from 'react-infinite-scroll-component';
import { Spin, SpinProps } from 'antd';
import { useSize } from '@zhst/hooks';
import './index.less'

const { ConfigContext } = ConfigProvider

export interface IData {
  key: string;
  title: string;
  index?: number;
  [k: string]: any;
}

export interface InfiniteListProps extends React.HtmlHTMLAttributes<HTMLDivElement> {
  type?: 'custom' | 'auto'
  prefixCls?: string;
  height?: number;
  itemRender?: (data?: IData, index?: number) => React.ReactNode
  loading?: boolean;      //
  data: IData[];
  targetId?: string;     // 滚动列表 ID
  loadMore?: (data?: any) => any;
  params?: {
    [key: string]: any;
  }
  hasMore: boolean;
  endMessage?: ReactNode
  loadingMessage?: ReactNode
  loadingProps?: SpinProps
}

export interface InfiniteListRefProps {
  scrollViewSize?: { width: number; height: number }
  listSize?: { width: number; height: number }
}

const InfiniteList = forwardRef<InfiniteListRefProps, InfiniteListProps>((props, ref) => {
  const {
    prefixCls: customizePrefixCls,
    height = 600,
    loading,
    type = 'auto',
    loadingMessage = <p style={{ textAlign: 'center' }}>加载中...</p>,
    targetId = 'scrollableDiv',
    itemRender = (data) => <div>{data?.title}</div>,
    hasMore,
    loadMore,
    data = [],
    endMessage = <div style={{ textAlign: 'center' }} >没有更多数据了...🤐</div>,
    style,
    loadingProps,
    className
  } = props
  const { getPrefixCls } = useContext(ConfigContext);
  const componentName = getPrefixCls('biz-infinite-list', customizePrefixCls);
  const listRef = useRef<HTMLDivElement>(null);
  const scrollRef = useRef<HTMLDivElement>(null);
  const scrollViewSize = useSize(listRef.current) || { width: 0, height: 0 };          // 无限滚动视窗大小
  // @ts-ignore
  const listSize = useSize(scrollRef.current?._infScroll) || { width: 0, height: 0 }    // 无限滚动列表大小

  useEffect(() => {
    // 当数据不够一屏时继续加载
    if (listSize.height < scrollViewSize.height) {
      loadMore?.()
    }
  }, [listSize.height])

  useImperativeHandle(ref, () => ({
    scrollViewSize,
    listSize
  }))

  return (
    <Spin spinning={loading} {...loadingProps}>
      <div
        id={targetId}
        className={classNames(componentName, className)}
        ref={listRef}
        style={{
          height,
          overflow: 'auto',
          ...style
        }}
      >
        <InfiniteScroll
          // @ts-ignore
          ref={scrollRef}
          dataLength={data.length}
          next={type === 'auto' ? loadMore! : () => {}}
          hasMore={hasMore}
          loader={loadingMessage}
          endMessage={endMessage}
          scrollableTarget={targetId}
        >
          {data?.map((item, idx) => (
            itemRender?.({ ...item, index: idx})
          ))}
        </InfiniteScroll>
      </div>
    </Spin>
  )
})

export default InfiniteList
