import React, { Component } from 'react';
import { createPopper } from '@popperjs/core';
import ReactDOM from 'react-dom';
import maxSize from './popper-max-size-modifier';
import { ReactPopperContext } from './react-popper-context';
import { jsx as _jsx } from "react/jsx-runtime";
export const POPPER_PLACEMENTS_TYPES = {
  BOTTOM_END: 'bottom-end',
  BOTTOM_START: 'bottom-start',
  BOTTOM: 'bottom',
  LEFT_END: 'left-end',
  LEFT_START: 'left-start',
  LEFT: 'left',
  RIGHT_END: 'right-end',
  RIGHT_START: 'right-start',
  RIGHT: 'right',
  TOP_END: 'top-end',
  TOP_START: 'top-start',
  TOP: 'top',
  AUTO: 'auto',
  AUTO_START: 'auto-start',
  AUTO_END: 'auto-end'
};
export const PopperPlacements = [POPPER_PLACEMENTS_TYPES.BOTTOM_END, POPPER_PLACEMENTS_TYPES.BOTTOM_START, POPPER_PLACEMENTS_TYPES.BOTTOM, POPPER_PLACEMENTS_TYPES.LEFT_END, POPPER_PLACEMENTS_TYPES.LEFT_START, POPPER_PLACEMENTS_TYPES.LEFT, POPPER_PLACEMENTS_TYPES.RIGHT_END, POPPER_PLACEMENTS_TYPES.RIGHT_START, POPPER_PLACEMENTS_TYPES.RIGHT, POPPER_PLACEMENTS_TYPES.TOP_END, POPPER_PLACEMENTS_TYPES.TOP_START, POPPER_PLACEMENTS_TYPES.TOP, POPPER_PLACEMENTS_TYPES.AUTO, POPPER_PLACEMENTS_TYPES.AUTO_START, POPPER_PLACEMENTS_TYPES.AUTO_END];
export const POPPER_STRATEGY_OPTIONS = {
  ABSOLUTE: 'absolute',
  FIXED: 'fixed'
};
export const OFFSET_MODIFIER = {
  name: 'offset',
  options: {
    offset: [0, 8]
  }
};
export const FLIP_MODIFIER = {
  name: 'flip',
  options: {
    fallbackPlacements: ['bottom', 'right', 'left', 'top']
  }
};
export const PREVENT_PARENT_OVERFLOW = {
  name: 'preventOverflow',
  options: {
    altAxis: true,
    altBoundary: true
  }
};
function getAnchorEl(anchorEl) {
  if (typeof anchorEl === 'function') {
    return anchorEl();
  }
  if (anchorEl?.ref?.current) {
    return anchorEl.ref.current;
  }
  return anchorEl;
}
export class Popper extends Component {
  static contextType = ReactPopperContext;
  constructor(props) {
    super(props);
    this.popper = null;
    this.hasChildPopper = false;
    this.state = {
      exited: !this.props.open,
      placement: this.props.placement
    };
    this.setHasChild = this.setHasChild.bind(this);
  }
  static defaultProps = {
    placement: 'bottom',
    transition: false,
    strategy: POPPER_STRATEGY_OPTIONS.ABSOLUTE,
    forceUpdateAfterOpen: false
  };
  componentDidMount() {
    this.handleOpen();
    if (this.context?.hasParentPopper) {
      this.context.notifyParentPopper();
    }
  }
  componentDidUpdate(prevProps) {
    if (prevProps.open !== this.props.open && !this.props.open && !this.props.transition) {
      this.handleClose();
    }
    if (prevProps.open !== this.props.open || prevProps.anchorEl !== this.props.anchorEl || prevProps.popperModifiers !== this.props.popperModifiers || prevProps.placement !== this.props.placement) {
      this.handleOpen();
      if (this.popper && (this.props.forceUpdateAfterOpen || this.hasChildPopper)) {
        this.popper.forceUpdate();
      }
    }
  }
  componentWillUnmount() {
    this.handleClose();
  }
  static getDerivedStateFromProps(nextProps) {
    if (nextProps.open) {
      return {
        exited: false
      };
    }
    if (!nextProps.transition) {
      return {
        exited: true
      };
    }
    return null;
  }
  handleOpen = () => {
    const {
      anchorEl,
      rootEl,
      open,
      placement,
      strategy,
      popperModifiers = []
    } = this.props;
    const popperNode = rootEl.current;
    if (!popperNode || !anchorEl || !open) {
      return;
    }
    if (this.popper) {
      this.popper.destroy();
      this.popper = null;
    }
    const applyMaxSize = {
      name: 'applyMaxSize',
      enabled: true,
      phase: 'beforeWrite',
      requires: ['maxSize'],
      fn({
        state
      }) {
        // The `maxSize` modifier provides this data
        const {
          width,
          height
        } = state.modifiersData.maxSize;
        state.styles.popper = {
          ...state.styles.popper,
          maxWidth: `${width}px`,
          maxHeight: `${height}px`
        };
      }
    };
    this.popper = createPopper(getAnchorEl(anchorEl), popperNode.wrapperRef || popperNode, Object.assign({}, {
      strategy,
      placement,
      modifiers: [maxSize, applyMaxSize, ...popperModifiers],
      onFirstUpdate: this.handlePopperUpdate
    }));
  };
  setHasChild = () => {
    this.hasChildPopper = true;
  };
  handlePopperUpdate = data => {
    if (data.placement !== this.state.placement) {
      this.setState({
        placement: data.placement
      });
    }
  };
  handleExited = () => {
    if (!this.props.open) {
      this.setState({
        exited: true
      });
      this.handleClose();
    }
  };
  handleClose = () => {
    if (!this.popper) {
      return;
    }
    this.popper.destroy();
    this.popper = null;
  };
  render() {
    const {
      children,
      keepMounted,
      container,
      open,
      transition
    } = this.props;
    const {
      exited,
      placement
    } = this.state;
    if (!keepMounted && !open && (!transition || exited)) {
      return null;
    }
    const childProps = {
      placement,
      transitionProps: transition ? {
        open,
        onExited: this.handleExited
      } : null
    };
    const popperComponent = /*#__PURE__*/ReactDOM.createPortal(children(childProps), container || document.querySelector('#react-pop') || document.body);
    return /*#__PURE__*/_jsx(ReactPopperContext.Provider, {
      value: {
        hasParentPopper: true,
        notifyParentPopper: this.setHasChild
      },
      children: popperComponent
    });
  }
}