private void setFullAddedElementsStateRight(SplitResult result, int elementCount, double height) {
    result
        .setRightElementSplitHeight(0, 0)
        .setRightColumnHeight(height)
        .setElementsAddedCount(elementCount)
        .setPageSplit(elementCount, false);

    bestResult.assignIfWorseThan(result);
  }
  private AtomicIncreaseResult iterateOnRight(
      int currentIndex,
      SplitResult currentResult,
      float elementTop,
      Iterator<AtomicIncreaseResult> iterator) {
    AtomicIncreaseResult lastIncreaseResult = null;

    currentResult
        .setRightColumnHeight(rightCTB.getCurrentHeight())
        .setRightElementSplitHeight(
            elementTop - rightCTB.getYLine(), sequence.getHeight(currentIndex));

    bestResult.assignIfWorseThan(currentResult);

    cycle:
    while (iterator.hasNext()) {
      AtomicIncreaseResult r = iterator.next();
      currentResult.setRightColumnHeight(rightCTB.getCurrentHeight());

      lastIncreaseResult = r;

      switch (r.type) {
        case PAGE_OVERFLOW:
          break cycle;
        case NORMAL:
          currentResult.setRightElementSplitHeight(
              elementTop - rightCTB.getYLine(), sequence.getHeight(currentIndex));
          bestResult.assignIfWorseThan(currentResult);
          break;
        case NO_MORE_CONTENT:
          // must be done in the main cycle
          //                    setFullAddedElementsStateRight(currentResult, currentIndex + 1,
          // rightCTB.getCurrentHeight());

          break cycle;
      }
    }
    return lastIncreaseResult == null
        ? new AtomicIncreaseResult(0, ColumnTextBuilder.GrowthResultType.NO_MORE_CONTENT)
        : lastIncreaseResult;
  }
  private void considerAddingToRight(int startAt, boolean hasNotFlushedText) {
    logger.trace(
        "adding to right, i: {}, leftHeight: {}, leftSplit: {}",
        startAt,
        currentLeftResult.leftColumnHeight,
        currentLeftResult.leftElementSplitHeight);

    // copy content from the left
    rightCTB.setACopy(leftCTB).setYLine(leftCTB.getTop());

    if (!hasNotFlushedText && sequence.isSpace(startAt)) {
      startAt++;
    }

    // we can flush what's left from the previous column
    if (rightCTB.hasMoreText()) {
      rightCTB.go(true);
    }

    currentRightResult.copyFrom(currentLeftResult);

    // copied from left method
    int i;

    List<Element> elements = sequence.getElements();

    final DirectContentAdder.Result quickResult =
        new DirectContentAdder(rightCTB)
            .setStartWith(leftCTB)
            .setStartAtIndex(startAt)
            .setQuickHeight(leftCTB.getCurrentHeight())
            .setSimulate(true)
            .go();

    i = quickResult.index;

    int elementsAdded = quickResult.contentLeft == null ? i : i - 1;

    bestResult.assignIfWorseThan(
        currentRightResult
            .setElementsAddedCount(elementsAdded) // todo!!!
            .setRightElementSplitHeight(0, 0)
            .setRightColumnHeight(rightCTB.getCurrentHeight())
            .setPageSplit(elementsAdded, quickResult.hasContentLeft(elements.size())));

    boolean pageOverFlow = false;

    if (quickResult.contentLeft != null) {
      rightCTB.copyContentFrom(quickResult.contentLeft);
      AtomicIncreaseResult lastResult =
          iterateOnRight(
              i - 1, currentRightResult, rightCTB.getTop(), rightCTB.newAtomicIteratorFor());
      if (lastResult.type == ColumnTextBuilder.GrowthResultType.PAGE_OVERFLOW) {
        pageOverFlow = true;
      }
    }

    if (i == elements.size()) {
      bestResult.assignIfWorseThan(
          currentRightResult
              .setRightElementSplitHeight(0, 0)
              .setRightColumnHeight(rightCTB.getCurrentHeight())
              .setElementsAddedCount(i)
              .setPageSplit(i, rightCTB.hasMoreText()));
    }

    if (pageOverFlow) return;

    elementsCycle:
    for (; i < elements.size(); i++) {
      Element el = elements.get(i);

      final SplitResult currentResult = currentRightResult;

      setFullAddedElementsStateRight(currentResult, i, rightCTB.getCurrentHeight());

      currentResult.setPageSplit(true); // temporary pessimism

      if (el instanceof SpaceElement) {
        // todo extract method
        SpaceElement space = (SpaceElement) el;

        bestResult.assignIfWorseThan(currentResult.setElementsAddedCount(i).setPageSplit(i, false));

        if (space.fits(rightCTB, origRectangle.getBottom())) {
          space.add(rightCTB, true);
        } else {
          if (rightCTB.getSimpleColumnRectangle().getBottom() - space.getHeight()
              < b.getDocument().bottom()) {
            break;
          }

          rightCTB.growBottom(space.getHeight()).setYLine(rightCTB.getYLine() - space.getHeight());
        }
      } else {
        float elementTop = rightCTB.getYLine();

        final Iterator<AtomicIncreaseResult> iterator = rightCTB.newAtomicIteratorFor(el);

        AtomicIncreaseResult lastResult = iterateOnRight(i, currentResult, elementTop, iterator);

        if (lastResult.type == ColumnTextBuilder.GrowthResultType.PAGE_OVERFLOW) {
          break;
        }
      }

      // element is fully added here
      currentResult
          .setRightColumnHeight(rightCTB.getCurrentHeight())
          .setRightElementSplitHeight(0, 0);

      bestResult.assignIfWorseThan(currentResult);
    }
  }