import { _ as _toConsumableArray } from '../toConsumableArray-dKQYsfpV.js';
import { _ as _slicedToArray } from '../slicedToArray-BB-AwwkK.js';
import { _ as _objectWithoutProperties } from '../objectWithoutProperties-TXwlfNxG.js';
import React__default from 'react';
import PropTypes from 'prop-types';

var _excluded = ["as", "loader", "completionMessage", "emptyMessage", "errorMessage", "initialPage", "loadFunction", "onError", "children", "threshold", "innerProps", "pageLimit", "scrollParentSelector", "scrollContentSelector"];

var getIsEnded = function getIsEnded(currentPage, pageLimit, isLoading, error) {
  return pageLimit && pageLimit === currentPage && !isLoading && !error;
};

var isEmpty = function isEmpty(items, isLoading, error) {
  return !items.length && !isLoading && !error;
};

var InfiniteScroll = function InfiniteScroll(_ref) {
  var _ref$as = _ref.as,
      Component = _ref$as === void 0 ? "div" : _ref$as,
      _ref$loader = _ref.loader,
      loader = _ref$loader === void 0 ? /*#__PURE__*/React__default.createElement("div", null, "Loading...") : _ref$loader,
      _ref$completionMessag = _ref.completionMessage,
      completionMessage = _ref$completionMessag === void 0 ? null : _ref$completionMessag,
      _ref$emptyMessage = _ref.emptyMessage,
      emptyMessage = _ref$emptyMessage === void 0 ? null : _ref$emptyMessage,
      _ref$errorMessage = _ref.errorMessage,
      errorMessage = _ref$errorMessage === void 0 ? null : _ref$errorMessage,
      _ref$initialPage = _ref.initialPage,
      initialPage = _ref$initialPage === void 0 ? 1 : _ref$initialPage,
      _ref$loadFunction = _ref.loadFunction,
      loadFunction = _ref$loadFunction === void 0 ? function () {
    return Promise.resolve([]);
  } : _ref$loadFunction,
      onError = _ref.onError,
      mapCallback = _ref.children,
      _ref$threshold = _ref.threshold,
      threshold = _ref$threshold === void 0 ? 500 : _ref$threshold,
      _ref$innerProps = _ref.innerProps,
      innerProps = _ref$innerProps === void 0 ? null : _ref$innerProps,
      _ref$pageLimit = _ref.pageLimit,
      pageLimit = _ref$pageLimit === void 0 ? 1000 : _ref$pageLimit,
      scrollParentSelector = _ref.scrollParentSelector,
      scrollContentSelector = _ref.scrollContentSelector,
      props = _objectWithoutProperties(_ref, _excluded);

  var _React$useState = React__default.useState(initialPage),
      _React$useState2 = _slicedToArray(_React$useState, 2),
      page = _React$useState2[0],
      setPage = _React$useState2[1];

  var _React$useState3 = React__default.useState([]),
      _React$useState4 = _slicedToArray(_React$useState3, 2),
      items = _React$useState4[0],
      setItems = _React$useState4[1];

  var _React$useState5 = React__default.useState(false),
      _React$useState6 = _slicedToArray(_React$useState5, 2),
      isLoading = _React$useState6[0],
      setIsLoading = _React$useState6[1];

  var _React$useState7 = React__default.useState(null),
      _React$useState8 = _slicedToArray(_React$useState7, 2),
      error = _React$useState8[0],
      setError = _React$useState8[1];

  var position = React__default.useRef(0);
  var thresholdReached = React__default.useRef(false);
  var abortRequest = React__default.useRef(false);
  var parentProps = innerProps !== null && innerProps !== void 0 ? innerProps : props;
  var isEnded = getIsEnded(page, pageLimit, isLoading, error);
  var scrollCb = React__default.useCallback(function (event) {
    var target = event.target;
    var scrollArea = scrollParentSelector ? document.querySelector(scrollParentSelector) : target.scrollingElement;
    var scrollContent = scrollContentSelector ? document.querySelector(scrollContentSelector) : scrollArea;
    var scrollContentHeight = scrollContent.offsetHeight;
    var scrollPosition = scrollArea.scrollTop;
    var windowHeight = window.innerHeight;
    var scrollDifference = scrollContentHeight - threshold - scrollPosition;

    if (scrollDifference <= windowHeight && !thresholdReached.current) {
      thresholdReached.current = true; // if scrolling down

      if (position.current < scrollPosition) {
        // Increase page number if below limit
        setPage(function (currentPage) {
          return pageLimit && pageLimit > currentPage ? currentPage + 1 : currentPage;
        });
      }
    }

    if (scrollDifference + threshold === windowHeight) {
      // End reached
      thresholdReached.current = false;
    }

    position.current = scrollPosition;
  }, [threshold, pageLimit, scrollParentSelector, scrollContentSelector]); // Page changes Effect

  React__default.useEffect(function () {
    // This should only load if page limit is not reached
    // and if it should not load for the initial page as
    // the loadfunction effect handles that.
    if (pageLimit && pageLimit >= page && page !== initialPage) {
      abortRequest.current = false;
      setIsLoading(true);
      loadFunction(page).then(function (newItems) {
        thresholdReached.current = false;

        if (!abortRequest.current) {
          setItems(function (currentItems) {
            return [].concat(_toConsumableArray(currentItems), _toConsumableArray(newItems));
          });
          setIsLoading(false);
        }
      })["catch"](function (error) {
        if (!abortRequest.current) {
          setError(error);
          setIsLoading(false);

          if (onError) {
            onError(error);
          }
        }
      });
    }

    return function () {
      abortRequest.current = true;
    }; // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [page, pageLimit, abortRequest]); // LoadFunction's dependency effect

  React__default.useEffect(function () {
    abortRequest.current = false;
    setIsLoading(true);
    loadFunction(page).then(function (newItems) {
      if (!abortRequest.current) {
        setItems(newItems);
        setIsLoading(false);
      }
    })["catch"](function (error) {
      if (!abortRequest.current) {
        setError(error);
        setIsLoading(false);

        if (onError) {
          onError(error);
        }
      }
    });
    return function () {
      abortRequest.current = true;
    }; // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [loadFunction]); // Scroll Effect

  React__default.useEffect(function () {
    var scroller = scrollParentSelector ? document.querySelector(scrollParentSelector) : window;

    if (scroller) {
      scroller.addEventListener("scroll", scrollCb);
    }

    return function () {
      if (scroller) {
        scroller.removeEventListener("scroll", scrollCb);
      }
    };
  }, [scrollCb, scrollParentSelector]);
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Component, parentProps, items.map(mapCallback)), isLoading && loader, isEmpty(items, isLoading, error) && emptyMessage, isEnded && completionMessage, error && errorMessage);
};

InfiniteScroll.propTypes = {
  as: PropTypes.elementType,
  loader: PropTypes.node,
  completionMessage: PropTypes.node,
  emptyMessage: PropTypes.node,
  errorMessage: PropTypes.node,
  initialPage: PropTypes.number,
  loadFunction: PropTypes.func.isRequired,
  children: PropTypes.func.isRequired,
  onError: PropTypes.func,
  threshold: PropTypes.number,
  innerProps: PropTypes.object,
  pageLimit: PropTypes.number,
  scrollParentSelector: PropTypes.string,
  scrollContentSelector: PropTypes.string
};

export { InfiniteScroll as default };
