/** @return Point in layered pane coordinate system */
  static Pair<Point, Short> chooseBestHintPosition(
      Project project,
      Editor editor,
      int line,
      int col,
      LightweightHint hint,
      boolean awtTooltip,
      short preferredPosition) {
    HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl();
    Dimension hintSize = hint.getComponent().getPreferredSize();
    JComponent editorComponent = editor.getComponent();
    JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane();

    Point p1;
    Point p2;
    boolean isLookupShown = LookupManager.getInstance(project).getActiveLookup() != null;
    if (isLookupShown) {
      p1 = hintManager.getHintPosition(hint, editor, HintManager.UNDER);
      p2 = hintManager.getHintPosition(hint, editor, HintManager.ABOVE);
    } else {
      LogicalPosition pos = new LogicalPosition(line, col);
      p1 = HintManagerImpl.getHintPosition(hint, editor, pos, HintManager.UNDER);
      p2 = HintManagerImpl.getHintPosition(hint, editor, pos, HintManager.ABOVE);
    }

    if (!awtTooltip) {
      p1.x = Math.min(p1.x, layeredPane.getWidth() - hintSize.width);
      p1.x = Math.max(p1.x, 0);
      p2.x = Math.min(p2.x, layeredPane.getWidth() - hintSize.width);
      p2.x = Math.max(p2.x, 0);
    }

    boolean p1Ok = p1.y + hintSize.height < layeredPane.getHeight();
    boolean p2Ok = p2.y >= 0;

    if (isLookupShown) {
      if (p1Ok) return new Pair<Point, Short>(p1, HintManager.UNDER);
      if (p2Ok) return new Pair<Point, Short>(p2, HintManager.ABOVE);
    } else {
      if (preferredPosition != HintManager.DEFAULT) {
        if (preferredPosition == HintManager.ABOVE) {
          if (p2Ok) return new Pair<Point, Short>(p2, HintManager.ABOVE);
        } else if (preferredPosition == HintManager.UNDER) {
          if (p1Ok) return new Pair<Point, Short>(p1, HintManager.UNDER);
        }
      }

      if (p1Ok) return new Pair<Point, Short>(p1, HintManager.UNDER);
      if (p2Ok) return new Pair<Point, Short>(p2, HintManager.ABOVE);
    }

    int underSpace = layeredPane.getHeight() - p1.y;
    int aboveSpace = p2.y;
    return aboveSpace > underSpace
        ? new Pair<Point, Short>(new Point(p2.x, 0), HintManager.UNDER)
        : new Pair<Point, Short>(p1, HintManager.ABOVE);
  }
    @Override
    @NotNull
    public Pair<Point, Short> getBestPointPosition(
        LightweightHint hint,
        final PsiElement list,
        int offset,
        final boolean awtTooltip,
        short preferredPosition) {
      if (list != null) {
        TextRange range = list.getTextRange();
        if (!range.contains(offset)) {
          offset = range.getStartOffset() + 1;
        }
      }
      if (previousOffset == offset) return Pair.create(previousBestPoint, previousBestPosition);

      final boolean isMultiline =
          list != null && StringUtil.containsAnyChar(list.getText(), "\n\r");
      final LogicalPosition pos = myEditor.offsetToLogicalPosition(offset);
      Pair<Point, Short> position;

      if (!isMultiline) {
        position =
            chooseBestHintPosition(
                myEditor.getProject(),
                myEditor,
                pos.line,
                pos.column,
                hint,
                awtTooltip,
                preferredPosition);
      } else {
        Point p = HintManagerImpl.getHintPosition(hint, myEditor, pos, HintManager.ABOVE);
        position = new Pair<Point, Short>(p, HintManager.ABOVE);
      }
      previousBestPoint = position.getFirst();
      previousBestPosition = position.getSecond();
      previousOffset = offset;
      return position;
    }