import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
// Copyright 1999-2020. Plesk International GmbH. All rights reserved.

/* eslint-disable react/no-deprecated */
import React, { cloneElement, Component, Fragment, createRef } from 'react';
import { findDOMNode } from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { CLS_PREFIX } from '../../constants';
import PopperJs from 'popper.js';
import Layer from '../Layer';
/**
 * `Popper` component.
 */

class Popper extends Component {
  constructor(...args) {
    super(...args);

    _defineProperty(this, "state", {
      popperStyle: null,
      arrowStyle: null,
      actualPlacement: this.props.placement
    });

    _defineProperty(this, "popper", null);

    _defineProperty(this, "contentRef", /*#__PURE__*/createRef());

    _defineProperty(this, "extractStyles", state => {
      if (!state) {
        return;
      }

      const {
        onUpdate
      } = this.props;
      const data = {
        popperStyle: {
          position: state.offsets.popper.position,
          ...(state.hide ? {
            visibility: 'hidden',
            pointerEvents: 'none'
          } : undefined),
          ...state.styles
        },
        actualPlacement: state.placement,
        arrowStyle: state.arrowStyles
      };
      this.setState(data);

      if (onUpdate) {
        onUpdate(data);
      }
    });
  }

  componentDidMount() {
    this.updatePopper(this.props);
  }

  componentDidUpdate(prevProps) {
    const {
      show,
      boundariesElement,
      placement,
      offset,
      behavior,
      arrow,
      children
    } = this.props;

    if (prevProps.show !== show || prevProps.boundariesElement !== boundariesElement || prevProps.placement !== placement || prevProps.offset !== offset || prevProps.behavior !== behavior || prevProps.arrow !== arrow || prevProps.children !== children) {
      setTimeout(() => {
        this.updatePopper(this.props);
      }, 0);
    }
  }

  componentWillUnmount() {
    if (this.popper) {
      this.popper.destroy();
    }
  }

  updatePopper({
    show,
    boundariesElement,
    placement,
    offset,
    behavior,
    arrow,
    targetRef
  }) {
    if (this.popper) {
      this.popper.destroy();
    }

    if (!this.contentRef.current || !show) {
      return;
    }

    const popperOpts = {
      placement,
      modifiers: {
        applyStyle: {
          enabled: false
        },
        applyReactStyle: {
          enabled: true,
          fn: this.extractStyles,
          order: 900
        },
        preventOverflow: {
          enabled: true,
          boundariesElement
        },
        hide: {
          enabled: true
        },
        offset: {
          enabled: true,
          offset
        },
        flip: {
          enabled: true,
          padding: 0,
          behavior
        },
        arrow: arrow && {
          enabled: true,
          element: this.arrowRef
        }
      }
    };
    let reference;

    if (targetRef && targetRef.current) {
      reference = targetRef.current;
    } else {
      reference = findDOMNode(this);
    }

    this.popper = new PopperJs(reference, this.contentRef.current, popperOpts);
  }

  render() {
    const {
      baseClassName,
      className,
      children,
      target,
      targetRef,
      arrow,
      placement,
      behavior,
      offset,
      onUpdate,
      zIndex,
      show,
      boundariesElement,
      style,
      ...props
    } = this.props;
    const {
      popperStyle
    } = this.state;
    const {
      arrowStyle,
      actualPlacement
    } = this.state;
    const arrowElement = arrow && /*#__PURE__*/cloneElement(arrow, {
      ref: ref => this.arrowRef = ref,
      style: arrowStyle
    });
    return /*#__PURE__*/React.createElement(Fragment, null, target, show ? /*#__PURE__*/React.createElement(Layer, {
      level: zIndex
    }, /*#__PURE__*/React.createElement("div", _extends({
      ref: this.contentRef,
      className: classNames(baseClassName, className, "".concat(baseClassName, "--placement-").concat(actualPlacement)),
      style: { ...style,
        ...(popperStyle ? popperStyle : {
          position: 'fixed',
          opacity: 0
        })
      }
    }, props), children, arrowElement)) : null);
  }

}

Popper.propTypes = {
  /**
   * Whether show popper content.
   */
  show: PropTypes.bool,

  /**
   * Content of the `Popper`.
   */
  children: PropTypes.node,

  /**
   * Target for popper.
   */
  target: PropTypes.any.isRequired,

  /**
   * A React reference to the DOM element that needs for calculating the position of the popup.
   */
  targetRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
    current: PropTypes.instanceOf(HTMLElement)
  })]),

  /**
   * Arrow element of popper
   */
  arrow: PropTypes.element,

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

  /**
   * The behavior used to change the popper's placement.
   */
  behavior: PropTypes.oneOfType([PropTypes.oneOf(['flip', 'clockwise', 'counterclockwise']), PropTypes.arrayOf(PropTypes.string)]),

  /**
   * Shift your popper on both axis.
   */
  offset: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

  /**
   * Update callback function
   */
  onUpdate: PropTypes.func,

  /**
   * @ignore
   */
  className: PropTypes.string,

  /**
   * @ignore
   */
  baseClassName: PropTypes.string,

  /**
   * zIndex value.
   */
  zIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

  /**
   * Boundaries element for preventOverflow property.
   */
  boundariesElement: PropTypes.oneOfType([PropTypes.oneOf(['scrollParent', 'window', 'viewport']), PropTypes.instanceOf(HTMLElement)]),

  /**
   * @ignore
   */
  style: PropTypes.object
};
Popper.defaultProps = {
  show: true,
  children: null,
  arrow: null,
  placement: 'bottom-start',
  behavior: 'flip',
  offset: '0, 0',
  onUpdate: null,
  className: null,
  baseClassName: "".concat(CLS_PREFIX, "popper"),
  zIndex: null,
  boundariesElement: 'window',
  style: undefined,
  targetRef: undefined
};
export default Popper;