// 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 COBALT_BOX_DUMP_ENABLED

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  // COBALT_BOX_DUMP_ENABLED

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
