import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

import { createBEM } from '@zarm-design/bem';
import throttle from 'lodash/throttle';
import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
import { ConfigContext } from '../config-provider';
import { canUseDOM } from '../utils/dom';
import Events from '../utils/events';
var DEFAULT_SCROLL_CONTAINER = canUseDOM ? window : undefined;
var Affix = /*#__PURE__*/forwardRef(function (props, ref) {
  var className = props.className,
      style = props.style,
      children = props.children,
      offsetBottom = props.offsetBottom,
      offsetTop = props.offsetTop,
      onChange = props.onChange,
      scrollContainer = props.scrollContainer;

  var _React$useContext = React.useContext(ConfigContext),
      prefixCls = _React$useContext.prefixCls;

  var bem = createBEM('affix', {
    prefixCls: prefixCls
  });
  var cls = bem([className]);

  var _useState = useState({
    affixed: false,
    width: 0,
    height: 0
  }),
      _useState2 = _slicedToArray(_useState, 2),
      affixState = _useState2[0],
      setAffixState = _useState2[1];

  var savePlaceholderNode = ref || /*#__PURE__*/React.createRef();
  var timerRef = useRef(0);
  var fixedNodeTopRef = useRef('offsetBottom' in props ? -10000 : 10000);
  var getContainer = useCallback(function () {
    var container = typeof scrollContainer === 'function' ? scrollContainer() : scrollContainer;
    return !container ? window : container;
  }, [scrollContainer]);

  var getContainerRect = function getContainerRect() {
    if (!canUseDOM) {
      return {
        top: 0,
        bottom: 0
      };
    }

    var container = getContainer();
    return container !== window ? container.getBoundingClientRect() : {
      top: 0,
      bottom: container.innerHeight,
      width: 0,
      height: 0
    };
  };

  var getAffixed = function getAffixed() {
    var containerRect = getContainerRect();

    if (typeof offsetBottom !== 'undefined' && fixedNodeTopRef.current + offsetBottom >= containerRect.bottom) {
      return true;
    }

    if (typeof offsetBottom === 'undefined' && typeof offsetTop !== 'undefined' && fixedNodeTopRef.current - offsetTop <= containerRect.top) {
      return true;
    }

    return false;
  };

  var onPositionUpdate = throttle(function () {
    var affixed = affixState.affixed;
    var target = savePlaceholderNode.current;

    if (!target) {
      return false;
    }

    var _target$getBoundingCl = target === null || target === void 0 ? void 0 : target.getBoundingClientRect(),
        top = _target$getBoundingCl.top,
        width = _target$getBoundingCl.width,
        height = _target$getBoundingCl.height;

    fixedNodeTopRef.current = top;
    var currentAffixed = getAffixed();

    if (currentAffixed !== affixed) {
      setAffixState({
        affixed: currentAffixed,
        // use 'auto' when get width or height is 0
        width: width === 0 ? 'auto' : width,
        height: height === 0 ? 'auto' : height
      });
      onChange && onChange(currentAffixed);
    }
  }, 10);

  var getAffixStyle = function getAffixStyle() {
    var containerRect = getContainerRect();
    var affixed = getAffixed();
    var width = affixState.width,
        height = affixState.height;

    if (affixed && offsetBottom != null) {
      return {
        position: 'fixed',
        bottom: offsetBottom,
        width: width,
        height: height
      };
    }

    if (affixed && offsetTop != null) {
      return {
        position: 'fixed',
        top: containerRect.top + offsetTop,
        width: width,
        height: height
      };
    }

    return {};
  };

  useEffect(function () {
    // wait for ref not null
    timerRef.current = window.setTimeout(function () {
      Events.on(getContainer(), 'scroll', onPositionUpdate);

      if (offsetBottom != null) {
        onPositionUpdate();
      }
    });
    return function () {
      var container = getContainer();
      Events.off(container, 'scroll', onPositionUpdate);
      window.clearTimeout(timerRef.current);
    };
  }, [getContainer, offsetBottom, onPositionUpdate]);
  return /*#__PURE__*/React.createElement("div", {
    ref: savePlaceholderNode
  }, /*#__PURE__*/React.createElement("div", {
    className: affixState.affixed ? cls : className,
    style: _objectSpread(_objectSpread({}, style), getAffixStyle())
  }, children));
});
Affix.displayName = 'Affix';
Affix.defaultProps = {
  scrollContainer: DEFAULT_SCROLL_CONTAINER,
  offsetTop: 0
};
export default Affix;