import { __awaiter } from "tslib";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useRef, forwardRef, useImperativeHandle, isValidElement, useContext } from 'react';
import clsx from 'clsx';
import Loading from '../loading';
import { getRect } from '../hooks/use-rect';
import useScrollParent from '../hooks/use-scroll-parent';
import useEventListener from '../hooks/use-event-listener';
import { isHidden } from '../utils';
import { useSetState, useUpdateEffect } from '../hooks';
import ConfigProviderContext from '../config-provider/ConfigProviderContext';
const List = forwardRef((props, ref) => {
  const {
    prefixCls,
    createNamespace,
    locale
  } = useContext(ConfigProviderContext);
  const [bem] = createNamespace('list', prefixCls);
  const [state, updateState] = useSetState({
    loading: props.loading,
    error: props.error
  });
  const root = useRef();
  const scrollParent = useRef(null);
  const placeholder = useRef();
  scrollParent.current = useScrollParent(root); // 判断是否需要加载

  const check = () => __awaiter(void 0, void 0, void 0, function* () {
    if (!props.onLoad) return;

    if (state.loading || props.finished || state.error) {
      return;
    }

    const {
      offset,
      direction
    } = props;
    const scrollParentRect = getRect(scrollParent.current);

    if (!scrollParentRect.height || isHidden(root.current)) {
      return;
    }

    let isReachEdge = false;
    const placeholderRect = getRect(placeholder.current);

    if (direction === 'up') {
      isReachEdge = scrollParentRect.top - placeholderRect.top <= offset;
    } else {
      isReachEdge = placeholderRect.bottom - scrollParentRect.bottom <= offset;
    }

    if (isReachEdge) {
      try {
        updateState({
          loading: true
        });
        if (props.onLoad) yield props.onLoad();
        updateState({
          loading: false
        });
      } catch (error) {
        // eslint-disable-next-line no-console
        console.warn('onLoad error:', error);
        updateState({
          loading: false,
          error: true
        });
      }
    }
  });

  const renderFinishedText = () => {
    if (props.finished && props.finishedText) {
      return _jsx("div", Object.assign({
        className: clsx(bem('finished-text'))
      }, {
        children: props.finishedText
      }));
    }

    return null;
  };

  const clickErrorText = () => {
    updateState({
      error: false
    });
    check();
  };

  const renderErrorText = () => {
    if (state.error && props.errorText) {
      return _jsx("div", Object.assign({
        className: clsx(bem('error-text')),
        onClick: clickErrorText
      }, {
        children: props.errorText
      }));
    }

    return null;
  };

  const renderLoading = () => {
    if (state.loading && !props.finished) {
      return _jsx("div", Object.assign({
        className: clsx(bem('loading'))
      }, {
        children: isValidElement(props.loadingText) ? props.loadingText : _jsx(Loading, Object.assign({
          className: clsx(bem('loading-icon')),
          size: 16
        }, {
          children: props.loadingText || locale.loading
        }))
      }));
    }

    return null;
  };

  useUpdateEffect(() => {
    if (props.autoCheck) {
      check();
    }
  }, [state.loading, props.finished, props.error]);
  useUpdateEffect(() => {
    updateState({
      loading: props.loading,
      error: props.error
    });
  }, [props.loading, props.error]);
  useUpdateEffect(() => {
    if (scrollParent.current && props.immediateCheck) {
      check();
    }
  }, [scrollParent.current]);
  useEventListener('scroll', check, {
    target: scrollParent.current,
    depends: [state.loading, props.finished, state.error]
  });
  useImperativeHandle(ref, () => ({
    check,
    state
  }));

  const Placeholder = _jsx("div", {
    ref: placeholder,
    className: clsx(bem('placeholder'))
  });

  return _jsxs("div", Object.assign({
    ref: root,
    role: "feed",
    className: clsx(bem(), props.className),
    style: props.style,
    "aria-busy": state.loading
  }, {
    children: [props.direction === 'down' ? props.children : Placeholder, renderLoading(), renderFinishedText(), renderErrorText(), props.direction === 'up' ? props.children : Placeholder]
  }));
});
List.defaultProps = {
  offset: 300,
  direction: 'down',
  immediateCheck: true,
  autoCheck: true
};
export default List;