// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/layout/inline_container_box.h"

#include <limits>

#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/line_box.h"
#include "cobalt/layout/used_style.h"

namespace cobalt {
namespace layout {

InlineContainerBox::InlineContainerBox(
    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
        css_computed_style_declaration,
    UsedStyleProvider* used_style_provider,
    LayoutStatTracker* layout_stat_tracker, BaseDirection base_direction)
    : ContainerBox(css_computed_style_declaration, used_style_provider,
                   layout_stat_tracker),
      should_collapse_leading_white_space_(false),
      should_collapse_trailing_white_space_(false),
      has_leading_white_space_(false),
      has_trailing_white_space_(false),
      is_collapsed_(false),
      justifies_line_existence_(false),
      first_box_justifying_line_existence_index_(0),
      used_font_(used_style_provider->GetUsedFontList(
          css_computed_style_declaration->data()->font_family(),
          css_computed_style_declaration->data()->font_size(),
          css_computed_style_declaration->data()->font_style(),
          css_computed_style_declaration->data()->font_weight())),
      is_split_on_left_(false),
      is_split_on_right_(false),
      base_direction_(base_direction) {}

InlineContainerBox::~InlineContainerBox() {}

Box::Level InlineContainerBox::GetLevel() const { return kInlineLevel; }

bool InlineContainerBox::TryAddChild(const scoped_refptr<Box>& child_box) {
  switch (child_box->GetLevel()) {
    case kBlockLevel:
      if (!child_box->IsAbsolutelyPositioned()) {
        // Only inline-level boxes are allowed as in-flow children of an inline
        // container box.
        return false;
      }
      // Fall through if out-of-flow.

    case kInlineLevel:
      // If the inline container box already contains a line break, then no
      // additional children can be added to it.
      if (HasTrailingLineBreak()) {
        return false;
      }

      PushBackDirectChild(child_box);
      return true;

    default:
      NOTREACHED();
      return false;
  }
}

scoped_refptr<ContainerBox> InlineContainerBox::TrySplitAtEnd() {
  scoped_refptr<InlineContainerBox> box_after_split(new InlineContainerBox(
      css_computed_style_declaration(), used_style_provider(),
      layout_stat_tracker(), base_direction_));
  // Set the state of where the sibling boxes are split using
  // base_direction_ to determine the correct way to split the boxes for
  // dir : rtl or ltr.
  if (base_direction_ == kLeftToRightBaseDirection) {
    is_split_on_right_ = true;
    box_after_split->SetIsSplitOnLeft(true);
  } else {
    is_split_on_left_ = true;
    box_after_split->SetIsSplitOnRight(true);
  }

  return box_after_split;
}

LayoutUnit InlineContainerBox::GetInlineLevelBoxHeight() const {
  return line_height_;
}

LayoutUnit InlineContainerBox::GetInlineLevelTopMargin() const {
  return inline_top_margin_;
}

void InlineContainerBox::SetIsSplitOnLeft(bool is_split_on_left) {
  is_split_on_left_ = is_split_on_left;
}

void InlineContainerBox::SetIsSplitOnRight(bool is_split_on_right) {
  is_split_on_right_ = is_split_on_right;
}

void InlineContainerBox::UpdateContentSizeAndMargins(
    const LayoutParams& layout_params) {
  // Lay out child boxes as one line without width constraints and white space
  // trimming.
  const render_tree::FontMetrics& font_metrics = used_font_->GetFontMetrics();
  LayoutUnit box_top_height = LayoutUnit(font_metrics.ascent());
  LineBox line_box(box_top_height, true, computed_style()->line_height(),
                   font_metrics, should_collapse_leading_white_space_,
                   should_collapse_trailing_white_space_, layout_params,
                   kLeftToRightBaseDirection, cssom::KeywordValue::GetLeft(),
                   computed_style()->font_size(), LayoutUnit(), LayoutUnit());

  for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
       child_box_iterator != child_boxes().end(); ++child_box_iterator) {
    line_box.BeginAddChildAndMaybeOverflow(child_box_iterator->get());
  }
  line_box.EndUpdates();

  if (!layout_params.freeze_width) {
    // Although the spec says:
    //
    // The "width" property does not apply.
    //   https://www.w3.org/TR/CSS21/visudet.html#inline-width
    //
    // ...it is not the entire truth. It merely means that we have to ignore
    // the computed value of "width". Instead we use the shrink-to-fit width of
    // a hypothetical line box that contains all children. Later on this allow
    // to apply the following rule:
    //
    // When an inline box exceeds the width of a line box, it is split into
    // several boxes.
    //   https://www.w3.org/TR/CSS21/visuren.html#inline-formatting
    set_width(line_box.shrink_to_fit_width());

    if (is_split_on_left_) {
      // When an inline box is split, margins, borders, and padding
      // have no visual effect where the split occurs. (or at any split, when
      // there are several).
      //   https://www.w3.org/TR/CSS21/visuren.html#inline-formatting
      set_margin_left(LayoutUnit());
    } else {
      // A computed value of "auto" for "margin-left" or "margin-right" becomes
      // a used value of "0".
      //   https://www.w3.org/TR/CSS21/visudet.html#inline-width
      base::Optional<LayoutUnit> maybe_margin_left = GetUsedMarginLeftIfNotAuto(
          computed_style(), layout_params.containing_block_size);
      set_margin_left(maybe_margin_left.value_or(LayoutUnit()));
    }

    if (is_split_on_right_) {
      // When an inline box is split, margins, borders, and padding
      // have no visual effect where the split occurs. (or at any split, when
      // there are several).
      //   https://www.w3.org/TR/CSS21/visuren.html#inline-formatting
      set_margin_right(LayoutUnit());
    } else {
      // A computed value of "auto" for "margin-left" or "margin-right" becomes
      // a used value of "0".
      //   https://www.w3.org/TR/CSS21/visudet.html#inline-width
      base::Optional<LayoutUnit> maybe_margin_right =
          GetUsedMarginRightIfNotAuto(computed_style(),
                                      layout_params.containing_block_size);
      set_margin_right(maybe_margin_right.value_or(LayoutUnit()));
    }
  }

  // The "height" property does not apply. The height of the content area should
  // be based on the font, but this specification does not specify how. [...]
  // However, we suggest that the height is chosen such that the content area
  // is just high enough for [...] the maximum ascenders and descenders, of all
  // the fonts in the element.
  //   https://www.w3.org/TR/CSS21/visudet.html#inline-non-replaced
  //
  // Above definition of used height matches the height of hypothetical line box
  // that contains all children.
  set_height(LayoutUnit(font_metrics.em_box_height()));

  // On a non-replaced inline element, 'line-height' specifies the height that
  // is used in the calculation of the line box height.
  //   https://www.w3.org/TR/CSS21/visudet.html#propdef-line-height
  line_height_ = line_box.height();

  // Vertical margins will not have any effect on non-replaced inline elements.
  //   https://www.w3.org/TR/CSS21/box.html#margin-properties
  set_margin_top(LayoutUnit());
  set_margin_bottom(LayoutUnit());
  inline_top_margin_ = line_box.baseline_offset_from_top() - line_box.top() -
                       border_top_width() - padding_top();

  has_leading_white_space_ = line_box.HasLeadingWhiteSpace();
  has_trailing_white_space_ = line_box.HasTrailingWhiteSpace();
  is_collapsed_ = line_box.IsCollapsed();
  justifies_line_existence_ =
      line_box.LineExists() || HasNonZeroMarginOrBorderOrPadding();
  first_box_justifying_line_existence_index_ =
      line_box.GetFirstBoxJustifyingLineExistenceIndex();
  baseline_offset_from_margin_box_top_ = line_box.baseline_offset_from_top();

  auto maybe_height = GetUsedHeightIfNotAuto(
      computed_style(), layout_params.containing_block_size, NULL);
  LayoutParams child_layout_params;
  LayoutParams absolute_child_layout_params;
  child_layout_params.containing_block_direction = base_direction_;
  absolute_child_layout_params.containing_block_direction = base_direction_;
  // If the element's position is "relative" or "static", the containing block
  // is formed by the content edge of the nearest block container ancestor
  // box.
  //   https://www.w3.org/TR/CSS21/visudet.html#containing-block-details
  child_layout_params.containing_block_size.set_width(width());
  // If the element has 'position: absolute', ...
  // the containing block is formed by the padding edge of the ancestor.
  //   http://www.w3.org/TR/CSS21/visudet.html#containing-block-details
  absolute_child_layout_params.containing_block_size.set_width(
      GetPaddingBoxWidth());
  child_layout_params.maybe_margin_top = LayoutUnit();
  child_layout_params.maybe_margin_bottom = LayoutUnit();
  child_layout_params.maybe_height = maybe_height;

  // Positioned children are laid out at the end as their position and size
  // depends on the size of the containing block as well as possibly their
  // previously calculated in-flow position.
  child_layout_params.containing_block_size.set_height(height());
  absolute_child_layout_params.containing_block_size.set_height(
      GetPaddingBoxHeight());
  UpdateRectOfPositionedChildBoxes(child_layout_params,
                                   absolute_child_layout_params);
}

void InlineContainerBox::UpdateBorders() {
  if (IsBorderStyleNoneOrHidden(computed_style()->border_left_style()) &&
      IsBorderStyleNoneOrHidden(computed_style()->border_top_style()) &&
      IsBorderStyleNoneOrHidden(computed_style()->border_right_style()) &&
      IsBorderStyleNoneOrHidden(computed_style()->border_bottom_style())) {
    ResetBorderInsets();
    return;
  }
  // When an inline box is split, margins, borders, and padding
  // have no visual effect where the split occurs. (or at any split, when there
  // are several).
  //   https://www.w3.org/TR/CSS21/visuren.html#inline-formatting
  SetBorderInsets(
      is_split_on_left_ ? LayoutUnit() : GetUsedBorderLeft(computed_style()),
      GetUsedBorderTop(computed_style()),
      is_split_on_right_ ? LayoutUnit() : GetUsedBorderRight(computed_style()),
      GetUsedBorderBottom(computed_style()));
}

void InlineContainerBox::UpdatePaddings(const LayoutParams& layout_params) {
  // When an inline box is split, margins, borders, and padding
  // have no visual effect where the split occurs. (or at any split, when there
  // are several).
  //   https://www.w3.org/TR/CSS21/visuren.html#inline-formatting
  SetPaddingInsets(
      is_split_on_left_
          ? LayoutUnit()
          : GetUsedPaddingLeft(computed_style(),
                               layout_params.containing_block_size),
      GetUsedPaddingTop(computed_style(), layout_params.containing_block_size),
      is_split_on_right_
          ? LayoutUnit()
          : GetUsedPaddingRight(computed_style(),
                                layout_params.containing_block_size),
      GetUsedPaddingBottom(computed_style(),
                           layout_params.containing_block_size));
}

WrapResult InlineContainerBox::TryWrapAt(
    WrapAtPolicy wrap_at_policy, WrapOpportunityPolicy wrap_opportunity_policy,
    bool is_line_existence_justified, LayoutUnit available_width,
    bool should_collapse_trailing_white_space) {
  DCHECK(!IsAbsolutelyPositioned());
  DCHECK(is_line_existence_justified || justifies_line_existence_);

  switch (wrap_at_policy) {
    case kWrapAtPolicyBefore:
      return TryWrapAtBefore(wrap_opportunity_policy,
                             is_line_existence_justified, available_width,
                             should_collapse_trailing_white_space);
    case kWrapAtPolicyLastOpportunityWithinWidth:
      return TryWrapAtLastOpportunityWithinWidth(
          wrap_opportunity_policy, is_line_existence_justified, available_width,
          should_collapse_trailing_white_space);
    case kWrapAtPolicyLastOpportunity:
      return TryWrapAtLastOpportunityBeforeIndex(
          child_boxes().size(), wrap_opportunity_policy,
          is_line_existence_justified, available_width,
          should_collapse_trailing_white_space);
    case kWrapAtPolicyFirstOpportunity:
      return TryWrapAtFirstOpportunity(
          wrap_opportunity_policy, is_line_existence_justified, available_width,
          should_collapse_trailing_white_space);
    default:
      NOTREACHED();
      return kWrapResultNoWrap;
  }
}

Box* InlineContainerBox::GetSplitSibling() const {
  return split_sibling_.get();
}

bool InlineContainerBox::DoesFulfillEllipsisPlacementRequirement() const {
  for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
       child_box_iterator != child_boxes().end(); ++child_box_iterator) {
    Box* child_box = child_box_iterator->get();
    if (child_box->DoesFulfillEllipsisPlacementRequirement()) {
      return true;
    }
  }

  return false;
}

void InlineContainerBox::DoPreEllipsisPlacementProcessing() {
  for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
       child_box_iterator != child_boxes().end(); ++child_box_iterator) {
    (*child_box_iterator)->DoPreEllipsisPlacementProcessing();
  }
}

void InlineContainerBox::DoPostEllipsisPlacementProcessing() {
  for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
       child_box_iterator != child_boxes().end(); ++child_box_iterator) {
    (*child_box_iterator)->DoPostEllipsisPlacementProcessing();
  }
}

bool InlineContainerBox::TrySplitAtSecondBidiLevelRun() {
  const int kInvalidLevel = -1;
  int last_level = kInvalidLevel;

  Boxes::const_iterator child_box_iterator = child_boxes().begin();
  while (child_box_iterator != child_boxes().end()) {
    Box* child_box = child_box_iterator->get();
    int current_level = child_box->GetBidiLevel().value_or(last_level);

    // If the last level isn't equal to the current level, then check on whether
    // or not the last level is kInvalidLevel. If it is, then no initial value
    // has been set yet. Otherwise, the intersection of two bidi levels has been
    // found where a split should occur.
    if (last_level != current_level) {
      if (last_level == kInvalidLevel) {
        last_level = current_level;
      } else {
        break;
      }
    }

    // Try to split the child box's internals.
    if (child_box->TrySplitAtSecondBidiLevelRun()) {
      child_box_iterator = InsertSplitSiblingOfDirectChild(child_box_iterator);
      break;
    }

    ++child_box_iterator;
  }

  // If the iterator reached the end, then no split was found.
  if (child_box_iterator == child_boxes().end()) {
    return false;
  }

  SplitAtIterator(child_box_iterator);
  return true;
}

base::Optional<int> InlineContainerBox::GetBidiLevel() const {
  if (!child_boxes().empty()) {
    return child_boxes().front()->GetBidiLevel();
  }

  return base::nullopt;
}

void InlineContainerBox::SetShouldCollapseLeadingWhiteSpace(
    bool should_collapse_leading_white_space) {
  if (should_collapse_leading_white_space_ !=
      should_collapse_leading_white_space) {
    should_collapse_leading_white_space_ = should_collapse_leading_white_space;
    InvalidateUpdateSizeInputs();
  }
}

void InlineContainerBox::SetShouldCollapseTrailingWhiteSpace(
    bool should_collapse_trailing_white_space) {
  if (should_collapse_trailing_white_space_ !=
      should_collapse_trailing_white_space) {
    should_collapse_trailing_white_space_ =
        should_collapse_trailing_white_space;
    InvalidateUpdateSizeInputs();
  }
}

bool InlineContainerBox::HasLeadingWhiteSpace() const {
  DCHECK_EQ(kInlineLevel, GetLevel());
  DCHECK_EQ(width(), width());  // Width should not be NaN.

  return has_leading_white_space_;
}

bool InlineContainerBox::HasTrailingWhiteSpace() const {
  DCHECK_EQ(kInlineLevel, GetLevel());
  DCHECK_EQ(width(), width());  // Width should not be NaN.

  return has_trailing_white_space_;
}

bool InlineContainerBox::IsCollapsed() const {
  DCHECK_EQ(kInlineLevel, GetLevel());
  DCHECK_EQ(width(), width());  // Width should not be NaN.

  return is_collapsed_;
}

bool InlineContainerBox::JustifiesLineExistence() const {
  return justifies_line_existence_;
}

bool InlineContainerBox::HasTrailingLineBreak() const {
  return !child_boxes().empty() && child_boxes().back()->HasTrailingLineBreak();
}

bool InlineContainerBox::AffectsBaselineInBlockFormattingContext() const {
  NOTREACHED() << "Should only be called in a block formatting context.";
  return true;
}

LayoutUnit InlineContainerBox::GetBaselineOffsetFromTopMarginEdge() const {
  return baseline_offset_from_margin_box_top_;
}

bool InlineContainerBox::IsTransformable() const { return false; }

#ifdef ENABLE_DEBUGGER

void InlineContainerBox::DumpClassName(std::ostream* stream) const {
  *stream << "InlineContainerBox ";
}

void InlineContainerBox::DumpProperties(std::ostream* stream) const {
  ContainerBox::DumpProperties(stream);

  *stream << std::boolalpha << "line_height=" << line_height_.toFloat() << " "
          << "inline_top_margin=" << inline_top_margin_.toFloat() << " "
          << "has_leading_white_space=" << has_leading_white_space_ << " "
          << "has_trailing_white_space=" << has_trailing_white_space_ << " "
          << "is_collapsed=" << is_collapsed_ << " "
          << "justifies_line_existence=" << justifies_line_existence_ << " "
          << std::noboolalpha;
}

#endif  // ENABLE_DEBUGGER

void InlineContainerBox::DoPlaceEllipsisOrProcessPlacedEllipsis(
    BaseDirection base_direction, LayoutUnit desired_offset,
    bool* is_placement_requirement_met, bool* is_placed,
    LayoutUnit* placed_offset) {
  // If the ellipsis hasn't been previously placed, but the placement
  // requirement is met and its desired offset comes before the content box's
  // start edge, then place the ellipsis at its desired position. This can occur
  // when the desired position falls between the start edge of the margin box
  // and the start edge of its content box.
  if (!*is_placed && *is_placement_requirement_met) {
    LayoutUnit content_box_start_edge_offset =
        GetContentBoxStartEdgeOffsetFromContainingBlock(base_direction);
    if ((base_direction == kRightToLeftBaseDirection &&
         desired_offset >= content_box_start_edge_offset) ||
        (base_direction != kRightToLeftBaseDirection &&
         desired_offset <= content_box_start_edge_offset)) {
      *is_placed = true;
      *placed_offset = desired_offset;
    }
  }

  bool was_placed_before_children = *is_placed;

  // Subtract the content box offset from the desired offset. This box's
  // children will treat its content box left edge as the base ellipsis offset
  // position, and the content box offset will be re-added after the ellipsis
  // is placed. This allows its children to only focus on their offset from
  // their containing block, and not worry about nested containing blocks.
  LayoutUnit content_box_offset =
      GetContentBoxLeftEdgeOffsetFromContainingBlock();
  desired_offset -= content_box_offset;

  // Walk each child box in base direction order attempting to place the
  // ellipsis and update the box's ellipsis state. Even after the ellipsis is
  // placed, subsequent boxes must still be processed, as their state my change
  // as a result of having an ellipsis preceding them on the line.
  if (base_direction == kRightToLeftBaseDirection) {
    for (Boxes::const_reverse_iterator child_box_iterator =
             child_boxes().rbegin();
         child_box_iterator != child_boxes().rend(); ++child_box_iterator) {
      Box* child_box = child_box_iterator->get();
      // Out-of-flow boxes are not impacted by ellipses.
      if (child_box->IsAbsolutelyPositioned()) {
        continue;
      }
      child_box->TryPlaceEllipsisOrProcessPlacedEllipsis(
          base_direction, desired_offset, is_placement_requirement_met,
          is_placed, placed_offset);
    }
  } else {
    for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
         child_box_iterator != child_boxes().end(); ++child_box_iterator) {
      Box* child_box = child_box_iterator->get();
      // Out-of-flow boxes are not impacted by ellipses.
      if (child_box->IsAbsolutelyPositioned()) {
        continue;
      }
      child_box->TryPlaceEllipsisOrProcessPlacedEllipsis(
          base_direction, desired_offset, is_placement_requirement_met,
          is_placed, placed_offset);
    }
  }

  // If the ellipsis was not placed prior to processing the child boxes, then it
  // is guaranteed that the placement location comes after the start edge of the
  // content box. The content box's offset needs to be added back to the placed
  // offset, so that the offset again references this box's containing block.
  // Additionally, in the event that the ellipsis was not placed within a child
  // box, it will now be placed.
  if (!was_placed_before_children) {
    // If the ellipsis hasn't been placed yet, then place the ellipsis at its
    // desired position. This case can occur when the desired position falls
    // between the end edge of the box's content and the end edge of the box's
    // margin. In this case, |is_placement_requirement_met| does not need to be
    // checked, as it is guaranteed that one of the child boxes met the
    // requirement.
    if (!(*is_placed)) {
      *is_placed = true;
      *placed_offset = desired_offset;
    }

    *placed_offset += content_box_offset;
  }
}

WrapResult InlineContainerBox::TryWrapAtBefore(
    WrapOpportunityPolicy wrap_opportunity_policy, bool is_line_requirement_met,
    LayoutUnit available_width, bool should_collapse_trailing_white_space) {
  // If there are no boxes within the inline container box, then there is no
  // first box to try to wrap before. This box does not provide a wrappable
  // point on its own. Additionally, if the line requirement has not been met
  // before this box, then no wrap is available.
  if (child_boxes().size() == 0 || !is_line_requirement_met) {
    return kWrapResultNoWrap;
  } else {
    // Otherwise, attempt to wrap before the first child box.
    return TryWrapAtIndex(0, kWrapAtPolicyBefore, wrap_opportunity_policy,
                          is_line_requirement_met, available_width,
                          should_collapse_trailing_white_space);
  }
}

WrapResult InlineContainerBox::TryWrapAtLastOpportunityWithinWidth(
    WrapOpportunityPolicy wrap_opportunity_policy,
    bool is_line_existence_justified, LayoutUnit available_width,
    bool should_collapse_trailing_white_space) {
  DCHECK(GetMarginBoxWidth().GreaterThanOrNaN(available_width));

  // Calculate the available width where the content begins. If the content
  // does not begin within the available width, then the wrap can only occur
  // before the inline container box.
  available_width -= GetContentBoxLeftEdgeOffsetFromMarginBox();
  if (available_width < LayoutUnit()) {
    return TryWrapAtBefore(wrap_opportunity_policy, is_line_existence_justified,
                           available_width,
                           should_collapse_trailing_white_space);
  }

  // Determine the child box where the overflow occurs. If the overflow does not
  // occur until after the end of the content, then the overflow index will be
  // set to the number of child boxes.
  size_t overflow_index = 0;
  while (overflow_index < child_boxes().size()) {
    Box* child_box = child_boxes()[overflow_index].get();
    // Absolutely positioned boxes are not included in width calculations.
    if (child_box->IsAbsolutelyPositioned()) {
      continue;
    }

    LayoutUnit child_width = child_box->GetMarginBoxWidth();
    if (child_width > available_width) {
      break;
    }
    available_width -= child_width;
    ++overflow_index;
  }

  // If the overflow occurs before the line is justified, then no wrap is
  // available.
  if (!is_line_existence_justified &&
      overflow_index < first_box_justifying_line_existence_index_) {
    return kWrapResultNoWrap;
  }

  // If the overflow occurred within the content and not after, then attempt to
  // wrap within the box that overflowed and return the result if the wrap is
  // successful.
  if (overflow_index < child_boxes().size()) {
    WrapResult wrap_result =
        TryWrapAtIndex(overflow_index, kWrapAtPolicyLastOpportunityWithinWidth,
                       wrap_opportunity_policy, is_line_existence_justified,
                       available_width, should_collapse_trailing_white_space);
    if (wrap_result != kWrapResultNoWrap) {
      return wrap_result;
    }
  }

  // If no wrap was found within the box that overflowed, then attempt to wrap
  // within an earlier child box.
  return TryWrapAtLastOpportunityBeforeIndex(
      overflow_index, wrap_opportunity_policy, is_line_existence_justified,
      available_width, should_collapse_trailing_white_space);
}

WrapResult InlineContainerBox::TryWrapAtLastOpportunityBeforeIndex(
    size_t index, WrapOpportunityPolicy wrap_opportunity_policy,
    bool is_line_existence_justified, LayoutUnit available_width,
    bool should_collapse_trailing_white_space) {
  WrapResult wrap_result = kWrapResultNoWrap;

  // If the line is already justified, then any child before the index is
  // potentially wrappable. Otherwise, children preceding the first box that
  // justifies the line's existence do not need to be checked, as they can
  // never be wrappable.
  size_t first_wrappable_index =
      is_line_existence_justified ? 0
                                  : first_box_justifying_line_existence_index_;

  // Iterate backwards through the children attempting to wrap until a wrap is
  // successful or the first wrappable index is reached.
  while (wrap_result == kWrapResultNoWrap && index > first_wrappable_index) {
    --index;
    wrap_result =
        TryWrapAtIndex(index, kWrapAtPolicyLastOpportunity,
                       wrap_opportunity_policy, is_line_existence_justified,
                       available_width, should_collapse_trailing_white_space);
  }

  return wrap_result;
}

WrapResult InlineContainerBox::TryWrapAtFirstOpportunity(
    WrapOpportunityPolicy wrap_opportunity_policy,
    bool is_line_existence_justified, LayoutUnit available_width,
    bool should_collapse_trailing_white_space) {
  WrapResult wrap_result = kWrapResultNoWrap;

  // If the line is already justified, then any child is potentially wrappable.
  // Otherwise, children preceding the first box that justifies the line's
  // existence do not need to be checked, as they can never be wrappable.
  size_t check_index = is_line_existence_justified
                           ? 0
                           : first_box_justifying_line_existence_index_;

  // Iterate forward through the children attempting to wrap until a wrap is
  // successful or all of the children have been attempted.
  for (; wrap_result == kWrapResultNoWrap && check_index < child_boxes().size();
       ++check_index) {
    wrap_result =
        TryWrapAtIndex(check_index, kWrapAtPolicyFirstOpportunity,
                       wrap_opportunity_policy, is_line_existence_justified,
                       available_width, should_collapse_trailing_white_space);
  }

  return wrap_result;
}

WrapResult InlineContainerBox::TryWrapAtIndex(
    size_t wrap_index, WrapAtPolicy wrap_at_policy,
    WrapOpportunityPolicy wrap_opportunity_policy,
    bool is_line_existence_justified, LayoutUnit available_width,
    bool should_collapse_trailing_white_space) {
  Box* child_box = child_boxes()[wrap_index].get();
  if (child_box->IsAbsolutelyPositioned()) {
    Boxes::const_iterator wrap_iterator =
        child_boxes().begin() + static_cast<int>(wrap_index);
    SplitAtIterator(wrap_iterator);
    return kWrapResultSplitWrap;
  }

  // Check for whether the line is justified before this child. If it is not,
  // then verify that the line is justified within this child. This function
  // should not be called for unjustified indices.
  bool is_line_existence_justified_before_index =
      is_line_existence_justified ||
      wrap_index > first_box_justifying_line_existence_index_;
  DCHECK(is_line_existence_justified_before_index ||
         wrap_index == first_box_justifying_line_existence_index_);

  WrapResult wrap_result = child_box->TryWrapAt(
      wrap_at_policy, wrap_opportunity_policy,
      is_line_existence_justified_before_index, available_width,
      should_collapse_trailing_white_space);
  // If the no wrap was found, then simply return out. There's nothing to do.
  if (wrap_result == kWrapResultNoWrap) {
    return kWrapResultNoWrap;
    // Otherwise, if the wrap is before the first child, then the wrap is
    // happening before the full inline container box and no split is
    // occurring.
    // When breaks happen before the first or the last character of a box,
    // the break occurs immediately before/after the box (at its margin edge)
    // rather than breaking the box between its content edge and the content.
    //   https://www.w3.org/TR/css-text-3/#line-breaking
  } else if (wrap_result == kWrapResultWrapBefore && wrap_index == 0) {
    return kWrapResultWrapBefore;
    // In all other cases, the inline container box is being split as a result
    // of the wrap.
  } else {
    Boxes::const_iterator wrap_iterator =
        child_boxes().begin() + static_cast<int>(wrap_index);
    // If the child was split during its wrap, then the split sibling that was
    // produced by the split needs to be added to the container's children.
    if (wrap_result == kWrapResultSplitWrap) {
      wrap_iterator = InsertSplitSiblingOfDirectChild(wrap_iterator);
    }

    SplitAtIterator(wrap_iterator);
    return kWrapResultSplitWrap;
  }
}

void InlineContainerBox::SplitAtIterator(
    Boxes::const_iterator child_split_iterator) {
  // Move the children after the split into a new box.
  scoped_refptr<InlineContainerBox> box_after_split(new InlineContainerBox(
      css_computed_style_declaration(), used_style_provider(),
      layout_stat_tracker(), base_direction_));

  // Set the state of where the sibling boxes are split using
  // base_direction_ to determine the correct way to split the boxes for
  // dir : rtl or ltr.
  if (base_direction_ == kLeftToRightBaseDirection) {
    is_split_on_right_ = true;
    box_after_split->SetIsSplitOnLeft(true);
  } else {
    is_split_on_left_ = true;
    box_after_split->SetIsSplitOnRight(true);
  }

  // Update the split sibling links.
  box_after_split->split_sibling_ = split_sibling_;
  split_sibling_ = box_after_split;

  // Now move the children, starting at the iterator, from this container to the
  // split sibling.
  MoveDirectChildrenToSplitSibling(child_split_iterator);

#ifdef _DEBUG
  // Make sure that the |UpdateContentSizeAndMargins| is called afterwards.

  set_width(LayoutUnit());
  set_height(LayoutUnit());

  set_margin_left(LayoutUnit());
  set_margin_top(LayoutUnit());
  set_margin_right(LayoutUnit());
  set_margin_bottom(LayoutUnit());
#endif  // _DEBUG
}

}  // namespace layout
}  // namespace cobalt
