import React, { useRef, useMemo, useContext } from 'react';
import clsx from 'clsx';
import useScrollParent from '../hooks/use-scroll-parent';
import useEventListener from '../hooks/use-event-listener';
import { getScrollTop, unitToPx, isHidden, getZIndexStyle, extend } from '../utils';
import { useSetState, useUpdateEffect, useVisibilityChange } from '../hooks';
import { getRect } from '../hooks/use-rect';
import ConfigProviderContext from '../config-provider/ConfigProviderContext';

var Sticky = function Sticky(props) {
  var _useContext = useContext(ConfigProviderContext),
      prefixCls = _useContext.prefixCls,
      createNamespace = _useContext.createNamespace;

  var _createNamespace = createNamespace('sticky', prefixCls),
      bem = _createNamespace[0];

  var _useSetState = useSetState({
    fixed: false,
    width: 0,
    height: 0,
    transform: 0
  }),
      state = _useSetState[0],
      updateState = _useSetState[1];

  var root = useRef(null);
  var scrollParent = useScrollParent(root);
  var offset = useMemo(function () {
    return unitToPx(props.position === 'top' ? props.offsetTop : props.offsetBottom);
  }, [props.position, props.offsetTop, props.offsetBottom]);
  var rootStyle = useMemo(function () {
    var fixed = state.fixed,
        height = state.height,
        width = state.width;

    if (fixed) {
      return {
        width: width + "px",
        height: height + "px"
      };
    }

    return null;
  }, [state.fixed, state.height, state.width]);
  var stickyStyle = useMemo(function () {
    var _extend;

    if (!state.fixed) {
      return null;
    }

    var style = extend(getZIndexStyle(props.zIndex), (_extend = {
      width: state.width + "px",
      height: state.height + "px"
    }, _extend[props.position] = offset + "px", _extend));

    if (state.transform) {
      style.transform = "translate3d(0, " + state.transform + "px, 0)";
    }

    return style;
  }, [props.position, state.fixed, offset, state.width, state.height, state.transform]);

  var emitScroll = function emitScroll(scrollTop, isFixed) {
    if (props.onScroll) {
      props.onScroll({
        scrollTop: scrollTop,
        isFixed: isFixed
      });
    }
  };

  var onScroll = function onScroll() {
    if (!root.current || isHidden(root.current)) {
      return;
    }

    var container = props.container,
        position = props.position;
    var rootRect = getRect(root.current);
    var scrollTop = getScrollTop(window);
    var newState = {};
    newState.width = rootRect.width;
    newState.height = rootRect.height;

    if (position === 'top') {
      // The sticky component should be kept inside the container element
      if (container) {
        var containerRect = getRect(container.current);
        var difference = containerRect.bottom - offset - newState.height;
        newState.fixed = offset > rootRect.top && containerRect.bottom > 0;
        newState.transform = difference < 0 ? difference : 0;
      } else {
        newState.fixed = offset > rootRect.top;
      }
    } else {
      var clientHeight = document.documentElement.clientHeight;

      if (container) {
        var _containerRect = getRect(container.current);

        var _difference = clientHeight - _containerRect.top - offset - newState.height;

        newState.fixed = clientHeight - offset < rootRect.bottom && clientHeight > _containerRect.top;
        newState.transform = _difference < 0 ? -_difference : 0;
      } else {
        newState.fixed = clientHeight - offset < rootRect.bottom;
      }
    }

    updateState(newState);
    emitScroll(scrollTop, newState.fixed);
  };

  useEventListener('scroll', onScroll, {
    target: scrollParent
  });
  useVisibilityChange(root, onScroll);
  useUpdateEffect(function () {
    props.onChange == null ? void 0 : props.onChange(state.fixed);
  }, [state.fixed]);
  return /*#__PURE__*/React.createElement("div", {
    ref: root,
    style: rootStyle
  }, /*#__PURE__*/React.createElement("div", {
    className: clsx(bem({
      fixed: state.fixed
    })),
    style: stickyStyle
  }, props.children));
};

Sticky.defaultProps = {
  offsetTop: 0,
  offsetBottom: 0,
  position: 'top'
};
export default Sticky;