"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.calculateToolbarPositionTrackHead = exports.calculateToolbarPositionOnCellSelection = exports.calculateToolbarPositionAboveSelection = void 0;
var _utils = require("@atlaskit/editor-prosemirror/utils");
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
var MAXIMUM_BROWSER_SCROLLBAR_WIDTH = 20;

/*
  Calculates the position of the floating toolbar relative to the selection.
  This is a re-implementation which closely matches the behaviour on Confluence renderer.
  The main difference is the popup is always above the selection.
  Things to consider:
  - popup is always above the selection
  - coordinates of head X and getBoundingClientRect() are absolute in client viewport (not including scroll offsets)
  - popup may appear in '.fabric-editor-popup-scroll-parent' (or body)
  - we use the toolbarRect to center align toolbar
  - use wrapperBounds to clamp values
  - editorView.dom bounds differ to wrapperBounds, convert at the end
*/
var calculateToolbarPositionAboveSelection = exports.calculateToolbarPositionAboveSelection = function calculateToolbarPositionAboveSelection(toolbarTitle) {
  return function (editorView, nextPos) {
    var toolbar = document.querySelector("div[aria-label=\"".concat(toolbarTitle, "\"]"));
    if (!toolbar) {
      return nextPos;
    }
    // scroll wrapper for full page, fall back to document body
    // Ignored via go/ees007
    // eslint-disable-next-line @atlaskit/editor/enforce-todo-comment-format
    // TODO: look into using getScrollGutterOptions()
    var scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
    var wrapperBounds = scrollWrapper.getBoundingClientRect();
    var selection = window && window.getSelection();
    var range = selection && !selection.isCollapsed && selection.getRangeAt(0);
    if (!range) {
      return nextPos;
    }
    var toolbarRect = toolbar.getBoundingClientRect();
    var _editorView$state$sel = editorView.state.selection,
      head = _editorView$state$sel.head,
      anchor = _editorView$state$sel.anchor;
    var topCoords = editorView.coordsAtPos(Math.min(head, anchor));
    var bottomCoords = editorView.coordsAtPos(Math.max(head, anchor) - Math.min(range.endOffset, 1));
    var top = (topCoords.top || 0) - toolbarRect.height * 1.5;
    var left = 0;
    // If not on the same line
    if (topCoords.top !== bottomCoords.top) {
      // selecting downwards
      if (head > anchor) {
        left = Math.max(topCoords.right, bottomCoords.right);
      } else {
        left = Math.min(topCoords.left, bottomCoords.left);
      }
      /*
           short selection above a long paragraph
           eg. short {<}heading
           The purpose of this text is to show the selection range{>}.
           The horizontal positioning should center around "heading",
           not where it ends at "range".
           Note: if it was "head<b>ing</b>" then it would only center
           around "head". Undesireable but matches the current renderer.
         */
      var cliffPosition = range.getClientRects()[0];
      if (cliffPosition.right < left) {
        left = cliffPosition.left + cliffPosition.width / 2;
      }
    } else {
      // Otherwise center on the single line selection
      left = topCoords.left + (bottomCoords.right - topCoords.left) / 2;
    }
    left -= toolbarRect.width / 2;
    // Place toolbar below selection if not sufficient space above
    if (top < wrapperBounds.top) {
      var _getCoordsBelowSelect = getCoordsBelowSelection(bottomCoords, toolbarRect);
      top = _getCoordsBelowSelect.top;
      left = _getCoordsBelowSelect.left;
    }
    // remap positions from browser document to wrapperBounds
    return {
      top: top - wrapperBounds.top + scrollWrapper.scrollTop,
      left: Math.max(0, left - wrapperBounds.left)
    };
  };
};

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
var calculateToolbarPositionTrackHead = exports.calculateToolbarPositionTrackHead = function calculateToolbarPositionTrackHead(toolbarTitle) {
  return function (editorView, nextPos) {
    var toolbar = document.querySelector("div[aria-label=\"".concat(toolbarTitle, "\"]"));
    if (!toolbar) {
      return nextPos;
    }
    // scroll wrapper for full page, fall back to document body
    // Ignored via go/ees007
    // eslint-disable-next-line @atlaskit/editor/enforce-todo-comment-format
    // TODO: look into using getScrollGutterOptions()
    var scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
    var wrapperBounds = scrollWrapper.getBoundingClientRect();
    var selection = window && window.getSelection();
    var moreRovoOptionsButton = document.querySelector('button[aria-label="More Rovo options"], [aria-label="More Rovo options"]');
    var isMoreRovoOptionsButtonVisible = !!moreRovoOptionsButton && moreRovoOptionsButton instanceof HTMLElement && !!moreRovoOptionsButton.offsetParent;
    var range = null;
    if (isMoreRovoOptionsButtonVisible) {
      if (selection && selection.getRangeAt && selection.rangeCount > 0) {
        var maybeRange = selection.getRangeAt(0);
        if (maybeRange instanceof Range) {
          range = maybeRange;
        }
      }
    } else {
      if (selection && !selection.isCollapsed && selection.getRangeAt && selection.rangeCount > 0) {
        var _maybeRange = selection.getRangeAt(0);
        if (_maybeRange instanceof Range) {
          range = _maybeRange;
        }
      }
    }
    if (!range) {
      return nextPos;
    }
    var toolbarRect = toolbar.getBoundingClientRect();
    var _editorView$state$sel2 = editorView.state.selection,
      head = _editorView$state$sel2.head,
      anchor = _editorView$state$sel2.anchor;
    var topCoords = editorView.coordsAtPos(Math.min(head, anchor));
    var bottomCoords = editorView.coordsAtPos(Math.max(head, anchor) - Math.min(range.endOffset, 1));
    var top;
    // If not the same line, display toolbar below.
    if (head > anchor && topCoords.top !== bottomCoords.top) {
      // We are taking the previous pos to the maxium, so avoid end of line positions
      // returning the next line's rect.
      top = (bottomCoords.top || 0) + toolbarRect.height / 1.15;
    } else {
      top = (topCoords.top || 0) - toolbarRect.height * 1.5;
    }
    var left = (head > anchor ? bottomCoords.right : topCoords.left) - toolbarRect.width / 2;
    // Place toolbar below selection if not sufficient space above
    if (top < wrapperBounds.top) {
      var _getCoordsBelowSelect2 = getCoordsBelowSelection(bottomCoords, toolbarRect);
      top = _getCoordsBelowSelect2.top;
      left = _getCoordsBelowSelect2.left;
    }
    var leftCoord = Math.max(0, left - wrapperBounds.left);
    if (leftCoord + toolbarRect.width > wrapperBounds.width) {
      var _scrollbarWidth = MAXIMUM_BROWSER_SCROLLBAR_WIDTH;
      leftCoord = Math.max(0, wrapperBounds.width - (toolbarRect.width + _scrollbarWidth));
    }

    // remap positions from browser document to wrapperBounds
    return {
      top: top - wrapperBounds.top + scrollWrapper.scrollTop,
      left: leftCoord
    };
  };
};

/**
 * Returns the coordintes at the bottom the selection.
 */
var getCoordsBelowSelection = function getCoordsBelowSelection(bottomCoords, toolbarRect) {
  return {
    top: (bottomCoords.top || 0) + toolbarRect.height / 1.15,
    left: bottomCoords.right - toolbarRect.width / 2
  };
};
var cellSelectionToolbarOffsetTop = 10;
var scrollbarWidth = 20;
var offsetTopOnColumnSelection = 4;
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
var calculateToolbarPositionOnCellSelection = exports.calculateToolbarPositionOnCellSelection = function calculateToolbarPositionOnCellSelection(toolbarTitle) {
  return function (editorView, nextPos) {
    var toolbar = document.querySelector("div[aria-label=\"".concat(toolbarTitle, "\"]"));
    if (!toolbar) {
      return nextPos;
    }
    var selection = editorView.state.selection;
    if (!(selection instanceof _cellSelection.CellSelection)) {
      return nextPos;
    }
    var $anchorCell = selection.$anchorCell,
      $headCell = selection.$headCell;
    var domAtPos = editorView.domAtPos.bind(editorView);
    var anchorCellDOM = (0, _utils.findDomRefAtPos)($anchorCell.pos, domAtPos);
    var headCellDOM = (0, _utils.findDomRefAtPos)($headCell.pos, domAtPos);
    if (!(anchorCellDOM instanceof HTMLElement) || !(headCellDOM instanceof HTMLElement)) {
      return nextPos;
    }
    var anchorCellRect = anchorCellDOM.getBoundingClientRect();
    var headCellRect = headCellDOM.getBoundingClientRect();
    var toolbarRect = toolbar.getBoundingClientRect();
    var top;
    if (headCellRect.top <= anchorCellRect.top) {
      // Display Selection toolbar at the top of the selection
      top = headCellRect.top - toolbarRect.height - cellSelectionToolbarOffsetTop;
    } else {
      // Display Selection toolbar at the bottom of the selection
      top = headCellRect.bottom + cellSelectionToolbarOffsetTop;
    }

    // scroll wrapper for full page, fall back to document body
    // Ignored via go/ees007
    // eslint-disable-next-line @atlaskit/editor/enforce-todo-comment-format
    // TODO: look into using getScrollGutterOptions()
    var scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
    var wrapperBounds = scrollWrapper.getBoundingClientRect();
    // Place toolbar below selection if not sufficient space above
    if (top < wrapperBounds.top && headCellRect.top <= anchorCellRect.top) {
      top = anchorCellRect.bottom + cellSelectionToolbarOffsetTop;
    }
    var left;
    if (headCellRect.left < anchorCellRect.left) {
      left = headCellRect.left;
    } else if (headCellRect.left === anchorCellRect.left) {
      left = headCellRect.left + headCellRect.width / 2;
    } else {
      left = headCellRect.right;
    }

    // If a user selected multiple columns via clicking on a drag handle
    // (clicking first on the left column and then shift clicking on the right column),
    // the $headcell stays in place and $anchorcell changes position. If they clicked on the right column
    // and then shift clicked on the left, the $headCell will change while $anchor stays in place.
    // Where is no way to know if user was dragging to select the cells or clicking on the drag handle.
    // So if all cells in columns are selected, we will align the Text Formatting toolbar
    // relative to center of the selected area.
    if (selection.isColSelection()) {
      if (headCellRect.left < anchorCellRect.left) {
        left = headCellRect.left + (anchorCellRect.right - headCellRect.left) / 2;
      } else if (headCellRect.left === anchorCellRect.left) {
        left = left;
      } else {
        left = anchorCellRect.left + (headCellRect.right - anchorCellRect.left) / 2;
      }

      // When column is selected, adjust top position to ensure that the toolbar does not
      // touch column drag handle
      top = top - offsetTopOnColumnSelection;
    }
    var adjustedLeft = Math.max(0, left - toolbarRect.width / 2 - wrapperBounds.left);
    if (adjustedLeft + toolbarRect.width > wrapperBounds.width) {
      adjustedLeft = Math.max(0, wrapperBounds.width - (toolbarRect.width + scrollbarWidth));
    }

    // If the toolbar is to be placed at the bottom of the selection (it happens when
    // there is no sufficient space above) and the bottom of the selection is not in the view,
    // place the toolbar at the bottom of the visible part of selection
    if (selection.isColSelection() && top + toolbarRect.height > wrapperBounds.bottom) {
      top = top - (top - wrapperBounds.bottom) - (toolbarRect.height + 2 * cellSelectionToolbarOffsetTop);
    }
    return {
      top: top - wrapperBounds.top + scrollWrapper.scrollTop,
      left: adjustedLeft
    };
  };
};