import { useCallback, useMemo, useRef } from 'react';
import hasClass from 'dom-helpers/hasClass';
import { useBootstrapPrefix } from './ThemeProvider';

function getMargins(element) {
  var styles = window.getComputedStyle(element);
  var top = parseFloat(styles.marginTop) || 0;
  var right = parseFloat(styles.marginRight) || 0;
  var bottom = parseFloat(styles.marginBottom) || 0;
  var left = parseFloat(styles.marginLeft) || 0;
  return {
    top: top,
    right: right,
    bottom: bottom,
    left: left
  };
}

export default function usePopperMarginModifiers() {
  var overlayRef = useRef(null);
  var margins = useRef(null);
  var arrowMargins = useRef(null);
  var popoverClass = useBootstrapPrefix(undefined, 'popover');
  var dropdownMenuClass = useBootstrapPrefix(undefined, 'dropdown-menu');
  var callback = useCallback(function (overlay) {
    if (!overlay || !(hasClass(overlay, popoverClass) || hasClass(overlay, dropdownMenuClass))) return;
    margins.current = getMargins(overlay);
    overlay.style.margin = '0';
    overlayRef.current = overlay;
  }, [popoverClass, dropdownMenuClass]);
  var offset = useMemo(function () {
    return {
      name: 'offset',
      options: {
        offset: function offset(_ref) {
          var placement = _ref.placement;
          if (!margins.current) return [0, 0];
          var _margins$current = margins.current,
              top = _margins$current.top,
              left = _margins$current.left,
              bottom = _margins$current.bottom,
              right = _margins$current.right;

          switch (placement.split('-')[0]) {
            case 'top':
              return [0, bottom];

            case 'left':
              return [0, right];

            case 'bottom':
              return [0, top];

            case 'right':
              return [0, left];

            default:
              return [0, 0];
          }
        }
      }
    };
  }, [margins]);
  var arrow = useMemo(function () {
    return {
      name: 'arrow',
      options: {
        padding: function padding() {
          // The options here are used for Popper 2.8.4 and up.
          // For earlier version, padding is handled in popoverArrowMargins below.
          if (!arrowMargins.current) {
            return 0;
          }

          var _arrowMargins$current = arrowMargins.current,
              top = _arrowMargins$current.top,
              right = _arrowMargins$current.right;
          var padding = top || right;
          return {
            top: padding,
            left: padding,
            right: padding,
            bottom: padding
          };
        }
      }
    };
  }, [arrowMargins]); // Converts popover arrow margin to arrow modifier padding

  var popoverArrowMargins = useMemo(function () {
    return {
      name: 'popoverArrowMargins',
      enabled: true,
      phase: 'main',
      fn: function fn() {
        return undefined;
      },
      requiresIfExists: ['arrow'],
      effect: function effect(_ref2) {
        var state = _ref2.state;

        if (!overlayRef.current || !state.elements.arrow || !hasClass(overlayRef.current, popoverClass)) {
          return undefined;
        }

        if (state.modifiersData['arrow#persistent']) {
          // @popperjs/core <= 2.8.3 uses arrow#persistent to pass padding to arrow modifier.
          var _getMargins = getMargins(state.elements.arrow),
              top = _getMargins.top,
              right = _getMargins.right;

          var padding = top || right;
          state.modifiersData['arrow#persistent'].padding = {
            top: padding,
            left: padding,
            right: padding,
            bottom: padding
          };
        } else {
          // @popperjs/core >= 2.8.4 gets the padding from the arrow modifier options,
          // so we'll get the margins here, and let the arrow modifier above pass
          // it to popper.
          arrowMargins.current = getMargins(state.elements.arrow);
        }

        state.elements.arrow.style.margin = '0';
        return function () {
          if (state.elements.arrow) state.elements.arrow.style.margin = '';
        };
      }
    };
  }, [popoverClass]);
  return [callback, [offset, arrow, popoverArrowMargins]];
}