import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import PopperJS from 'popper.js';
import Portal from '../portal';

function getAnchorEl(anchorEl) {
  return typeof anchorEl === 'function' ? anchorEl() : anchorEl;
}
/**
 * Poppers rely on the 3rd party library [Popper.js](https://github.com/FezVrasta/popper.js) for positioning.
 */


var Popper =
/*#__PURE__*/
function (_React$Component) {
  _inherits(Popper, _React$Component);

  _createClass(Popper, null, [{
    key: "getDerivedStateFromProps",
    value: function getDerivedStateFromProps(nextProps) {
      if (nextProps.open) {
        return {
          exited: false
        };
      }

      if (!nextProps.transition) {
        // Otherwise let handleExited take care of marking exited.
        return {
          exited: true
        };
      }

      return null;
    }
  }]);

  function Popper(props) {
    var _this;

    _classCallCheck(this, Popper);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(Popper).call(this));

    _defineProperty(_assertThisInitialized(_this), "handleOpen", function () {
      var _this$props = _this.props,
          anchorEl = _this$props.anchorEl,
          modifiers = _this$props.modifiers,
          open = _this$props.open,
          placement = _this$props.placement,
          _this$props$popperOpt = _this$props.popperOptions,
          popperOptions = _this$props$popperOpt === void 0 ? {} : _this$props$popperOpt,
          disablePortal = _this$props.disablePortal;
      var popperNode = ReactDOM.findDOMNode(_assertThisInitialized(_this));

      if (!popperNode || !anchorEl || !open) {
        return;
      }

      if (_this.popper) {
        _this.popper.destroy();

        _this.popper = null;
      }

      _this.popper = new PopperJS(getAnchorEl(anchorEl), popperNode, _objectSpread({
        placement: placement
      }, popperOptions, {
        modifiers: _objectSpread({}, disablePortal ? {} : {
          // It's using scrollParent by default, we can use the viewport when using a portal.
          preventOverflow: {
            boundariesElement: 'window'
          }
        }, modifiers, popperOptions.modifiers),
        // We could have been using a custom modifier like react-popper is doing.
        // But it seems this is the best public API for this use case.
        onCreate: _this.handlePopperUpdate,
        onUpdate: _this.handlePopperUpdate
      }));
    });

    _defineProperty(_assertThisInitialized(_this), "handlePopperUpdate", function (data) {
      var placement = _this.state.placement;

      if (data.placement !== placement) {
        _this.setState({
          placement: data.placement
        });
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleExited", function () {
      _this.setState({
        exited: true
      });

      _this.handleClose();
    });

    _defineProperty(_assertThisInitialized(_this), "handleClose", function () {
      if (!_this.popper) {
        return;
      }

      _this.popper.destroy();

      _this.popper = null;
    });

    _this.state = {
      exited: !props.open
    };
    return _this;
  }

  _createClass(Popper, [{
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps) {
      var _this$props2 = this.props,
          open = _this$props2.open,
          transition = _this$props2.transition,
          anchorEl = _this$props2.anchorEl,
          popperOptions = _this$props2.popperOptions,
          modifiers = _this$props2.modifiers,
          disablePortal = _this$props2.disablePortal,
          placement = _this$props2.placement;

      if (prevProps.open !== open && !open && !transition) {
        // Otherwise handleExited will call this.
        this.handleClose();
      } // Let's update the popper position.


      if (prevProps.open !== open || prevProps.anchorEl !== anchorEl || prevProps.popperOptions !== popperOptions || prevProps.modifiers !== modifiers || prevProps.disablePortal !== disablePortal || prevProps.placement !== placement) {
        this.handleOpen();
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      this.handleClose();
    }
  }, {
    key: "render",
    value: function render() {
      var _this$props3 = this.props,
          anchorEl = _this$props3.anchorEl,
          children = _this$props3.children,
          container = _this$props3.container,
          disablePortal = _this$props3.disablePortal,
          keepMounted = _this$props3.keepMounted,
          modifiers = _this$props3.modifiers,
          open = _this$props3.open,
          placementProps = _this$props3.placement,
          popperOptions = _this$props3.popperOptions,
          transition = _this$props3.transition,
          other = _objectWithoutProperties(_this$props3, ["anchorEl", "children", "container", "disablePortal", "keepMounted", "modifiers", "open", "placement", "popperOptions", "transition"]);

      var _this$state = this.state,
          exited = _this$state.exited,
          placement = _this$state.placement;

      if (!keepMounted && !open && (!transition || exited)) {
        return null;
      }

      var childProps = {
        placement: placement
      };

      if (transition) {
        childProps.TransitionProps = {
          in: open,
          onExited: this.handleExited
        };
      }

      return React.createElement(Portal, {
        onRendered: this.handleOpen,
        disablePortal: disablePortal,
        container: container
      }, React.createElement("div", _extends({
        role: "tooltip",
        style: {
          // Prevents scroll issue, waiting for Popper.js to add this style once initiated.
          position: 'absolute'
        }
      }, other), typeof children === 'function' ? children(childProps) : children));
    }
  }]);

  return Popper;
}(React.Component);

Popper.propTypes = {
  /**
   * This is the DOM element, or a function that returns the DOM element,
   * that may be used to set the position of the popover.
   * The return value will passed as the reference object of the Popper
   * instance.
   */
  anchorEl: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),

  /**
   * Popper render function or node.
   */
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,

  /**
   * A node, component instance, or function that returns either.
   * The `container` will passed to the Modal component.
   * By default, it uses the body of the anchorEl's top-level document object,
   * so it's simply `document.body` most of the time.
   */
  container: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),

  /**
   * Disable the portal behavior.
   * The children stay within it's parent DOM hierarchy.
   */
  disablePortal: PropTypes.bool,

  /**
   * Always keep the children in the DOM.
   * This property can be useful in SEO situation or
   * when you want to maximize the responsiveness of the Popper.
   */
  keepMounted: PropTypes.bool,

  /**
   * Popper.js is based on a "plugin-like" architecture,
   * most of its features are fully encapsulated "modifiers".
   *
   * A modifier is a function that is called each time Popper.js needs to
   * compute the position of the popper.
   * For this reason, modifiers should be very performant to avoid bottlenecks.
   * To learn how to create a modifier, [read the modifiers documentation](https://github.com/FezVrasta/popper.js/blob/master/docs/_includes/popper-documentation.md#modifiers--object).
   */
  modifiers: PropTypes.object,

  /**
   * If `true`, the popper is visible.
   */
  open: PropTypes.bool.isRequired,

  /**
   * Popper placement.
   */
  placement: PropTypes.oneOf(['bottom-end', 'bottom-start', 'bottom', 'left-end', 'left-start', 'left', 'right-end', 'right-start', 'right', 'top-end', 'top-start', 'top']),

  /**
   * Options provided to the [`popper.js`](https://github.com/FezVrasta/popper.js) instance.
   */
  popperOptions: PropTypes.object,

  /**
   * Help supporting a react-transition-group/Transition component.
   */
  transition: PropTypes.bool
};
Popper.defaultProps = {
  disablePortal: false,
  placement: 'bottom',
  transition: false
};
export default Popper;