// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/layout/ng/ng_block_layout_algorithm.h"

#include "core/layout/ng/ng_absolute_utils.h"
#include "core/layout/ng/ng_block_break_token.h"
#include "core/layout/ng/ng_column_mapper.h"
#include "core/layout/ng/ng_constraint_space.h"
#include "core/layout/ng/ng_constraint_space_builder.h"
#include "core/layout/ng/ng_fragment.h"
#include "core/layout/ng/ng_fragment_builder.h"
#include "core/layout/ng/ng_layout_opportunity_iterator.h"
#include "core/layout/ng/ng_length_utils.h"
#include "core/layout/ng/ng_out_of_flow_layout_part.h"
#include "core/layout/ng/ng_units.h"
#include "core/style/ComputedStyle.h"
#include "platform/LengthFunctions.h"
#include "wtf/Optional.h"

namespace blink {
namespace {

// Updates the fragment's BFC offset if it's not already set.
void UpdateFragmentBfcOffset(const NGLogicalOffset& offset,
                             const NGConstraintSpace& space,
                             NGFragmentBuilder* builder) {
  NGLogicalOffset fragment_offset =
      space.IsNewFormattingContext() ? NGLogicalOffset() : offset;
  if (!builder->BfcOffset())
    builder->SetBfcOffset(fragment_offset);
}

// Adjusts content_size to respect the CSS "clear" property.
// Picks up the maximum between left/right exclusions and content_size depending
// on the value of style.clear() property.
void AdjustToClearance(const std::shared_ptr<NGExclusions>& exclusions,
                       const ComputedStyle& style,
                       const NGLogicalOffset& from_offset,
                       LayoutUnit* content_size) {
  DCHECK(content_size) << "content_size cannot be null here";
  const NGExclusion* right_exclusion = exclusions->last_right_float;
  const NGExclusion* left_exclusion = exclusions->last_left_float;

  LayoutUnit left_block_end_offset = *content_size;
  if (left_exclusion) {
    left_block_end_offset = std::max(
        left_exclusion->rect.BlockEndOffset() - from_offset.block_offset,
        *content_size);
  }
  LayoutUnit right_block_end_offset = *content_size;
  if (right_exclusion) {
    right_block_end_offset = std::max(
        right_exclusion->rect.BlockEndOffset() - from_offset.block_offset,
        *content_size);
  }

  switch (style.clear()) {
    case EClear::kNone:
      return;  // nothing to do here.
    case EClear::kLeft:
      *content_size = left_block_end_offset;
      break;
    case EClear::kRight:
      *content_size = right_block_end_offset;
      break;
    case EClear::kBoth:
      *content_size = std::max(left_block_end_offset, right_block_end_offset);
      break;
    default:
      ASSERT_NOT_REACHED();
  }
}

// Creates an exclusion from the fragment that will be placed in the provided
// layout opportunity.
NGExclusion CreateExclusion(const NGFragment& fragment,
                            const NGLayoutOpportunity& opportunity,
                            const LayoutUnit float_offset,
                            const NGBoxStrut& margins,
                            NGExclusion::Type exclusion_type) {
  NGExclusion exclusion;
  exclusion.type = exclusion_type;
  NGLogicalRect& rect = exclusion.rect;
  rect.offset = opportunity.offset;
  rect.offset.inline_offset += float_offset;

  rect.size.inline_size = fragment.InlineSize() + margins.InlineSum();
  rect.size.block_size = fragment.BlockSize() + margins.BlockSum();
  return exclusion;
}

// Adjusts the provided offset to the top edge alignment rule.
// Top edge alignment rule: the outer top of a floating box may not be higher
// than the outer top of any block or floated box generated by an element
// earlier in the source document.
NGLogicalOffset AdjustToTopEdgeAlignmentRule(const NGConstraintSpace& space,
                                             const NGLogicalOffset& offset) {
  NGLogicalOffset adjusted_offset = offset;
  LayoutUnit& adjusted_block_offset = adjusted_offset.block_offset;
  if (space.Exclusions()->last_left_float)
    adjusted_block_offset =
        std::max(adjusted_block_offset,
                 space.Exclusions()->last_left_float->rect.BlockStartOffset());
  if (space.Exclusions()->last_right_float)
    adjusted_block_offset =
        std::max(adjusted_block_offset,
                 space.Exclusions()->last_right_float->rect.BlockStartOffset());
  return adjusted_offset;
}

// Finds a layout opportunity for the fragment.
// It iterates over all layout opportunities in the constraint space and returns
// the first layout opportunity that is wider than the fragment or returns the
// last one which is always the widest.
//
// @param space Constraint space that is used to find layout opportunity for
//              the fragment.
// @param fragment Fragment that needs to be placed.
// @param origin_point {@code space}'s offset relative to the space that
//                     establishes a new formatting context that we're currently
//                     in and where all our exclusions reside.
// @param margins Margins of the fragment.
// @return Layout opportunity for the fragment.
const NGLayoutOpportunity FindLayoutOpportunityForFragment(
    NGConstraintSpace* space,
    const NGFragment& fragment,
    const NGLogicalOffset& origin_point,
    const NGBoxStrut& margins) {
  NGLogicalOffset adjusted_origin_point =
      AdjustToTopEdgeAlignmentRule(*space, origin_point);

  NGLayoutOpportunityIterator* opportunity_iter =
      space->LayoutOpportunities(adjusted_origin_point);
  NGLayoutOpportunity opportunity;
  NGLayoutOpportunity opportunity_candidate = opportunity_iter->Next();

  while (!opportunity_candidate.IsEmpty()) {
    opportunity = opportunity_candidate;
    // Checking opportunity's block size is not necessary as a float cannot be
    // positioned on top of another float inside of the same constraint space.
    auto fragment_inline_size = fragment.InlineSize() + margins.InlineSum();
    if (opportunity.size.inline_size >= fragment_inline_size)
      break;
    opportunity_candidate = opportunity_iter->Next();
  }
  return opportunity;
}

// Calculates the logical offset for opportunity.
NGLogicalOffset CalculateLogicalOffsetForOpportunity(
    const NGLayoutOpportunity& opportunity,
    const LayoutUnit float_offset,
    const NGBoxStrut& margins,
    const NGLogicalOffset& space_offset) {
  // Adjust to child's margin.
  LayoutUnit inline_offset = margins.inline_start;
  LayoutUnit block_offset = margins.block_start;

  // Offset from the opportunity's block/inline start.
  inline_offset += opportunity.offset.inline_offset;
  block_offset += opportunity.offset.block_offset;

  inline_offset += float_offset;

  block_offset -= space_offset.block_offset;
  inline_offset -= space_offset.inline_offset;

  return NGLogicalOffset(inline_offset, block_offset);
}

// Calculates the relative position from {@code from_offset} of the
// floating object that is requested to be positioned from {@code origin_point}.
NGLogicalOffset PositionFloat(const NGLogicalOffset& origin_point,
                              const NGLogicalOffset& from_offset,
                              NGFloatingObject* floating_object) {
  NGConstraintSpace* float_space = floating_object->space;
  DCHECK(floating_object->fragment) << "Fragment cannot be null here";
  NGBoxFragment* float_fragment =
      new NGBoxFragment(float_space->WritingMode(), float_space->Direction(),
                        toNGPhysicalBoxFragment(floating_object->fragment));
  // Find a layout opportunity that will fit our float.
  const NGLayoutOpportunity opportunity =
      FindLayoutOpportunityForFragment(floating_object->space, *float_fragment,
                                       origin_point, floating_object->margins);
  DCHECK(!opportunity.IsEmpty()) << "Opportunity is empty but it shouldn't be";

  // Calculate the float offset if needed.
  LayoutUnit float_offset;
  if (floating_object->exclusion_type == NGExclusion::kFloatRight) {
    float_offset = opportunity.size.inline_size - float_fragment->InlineSize();
  }

  // Add the float as an exclusion.
  const NGExclusion exclusion = CreateExclusion(
      *float_fragment, opportunity, float_offset, floating_object->margins,
      floating_object->exclusion_type);
  float_space->AddExclusion(exclusion);

  return CalculateLogicalOffsetForOpportunity(
      opportunity, float_offset, floating_object->margins, from_offset);
}

// Positions pending floats stored on the fragment builder starting from
// {@code origin_point}.
void PositionPendingFloats(const NGLogicalOffset& origin_point,
                           NGFragmentBuilder* builder) {
  DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here";
  NGLogicalOffset from_offset = builder->BfcOffset().value();

  for (auto& floating_object : builder->UnpositionedFloats()) {
    NGLogicalOffset float_fragment_offset =
        PositionFloat(origin_point, from_offset, floating_object);
    builder->AddFloatingObject(floating_object, float_fragment_offset);
  }
  builder->MutableUnpositionedFloats().clear();
}

// Whether an in-flow block-level child creates a new formatting context.
//
// This will *NOT* check the following cases:
//  - The child is out-of-flow, e.g. floating or abs-pos.
//  - The child is a inline-level, e.g. "display: inline-block".
//  - The child establishes a new formatting context, but should be a child of
//    another layout algorithm, e.g. "display: table-caption" or flex-item.
bool IsNewFormattingContextForInFlowBlockLevelChild(
    const NGConstraintSpace& space,
    const ComputedStyle& style) {
  // TODO(layout-dev): This doesn't capture a few cases which can't be computed
  // directly from style yet:
  //  - The child is a <fieldset>.
  //  - "column-span: all" is set on the child (requires knowledge that we are
  //    in a multi-col formatting context).
  //    (https://drafts.csswg.org/css-multicol-1/#valdef-column-span-all)

  if (style.specifiesColumns() || style.containsPaint() ||
      style.containsLayout())
    return true;

  if (!style.isOverflowVisible())
    return true;

  EDisplay display = style.display();
  if (display == EDisplay::Grid || display == EDisplay::Flex ||
      display == EDisplay::WebkitBox)
    return true;

  if (space.WritingMode() != FromPlatformWritingMode(style.getWritingMode()))
    return true;

  return false;
}

}  // namespace

NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(
    LayoutObject* layout_object,
    PassRefPtr<const ComputedStyle> style,
    NGBlockNode* first_child,
    NGConstraintSpace* constraint_space,
    NGBreakToken* break_token)
    : style_(style),
      first_child_(first_child),
      constraint_space_(constraint_space),
      break_token_(break_token),
      builder_(new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox,
                                     layout_object)) {
  DCHECK(style_);
}

bool NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes(
    MinAndMaxContentSizes* sizes) const {
  sizes->min_content = LayoutUnit();
  sizes->max_content = LayoutUnit();

  // Size-contained elements don't consider their contents for intrinsic sizing.
  if (Style().containsSize())
    return true;

  // TODO: handle floats & orthogonal children.
  for (NGBlockNode* node = first_child_; node; node = node->NextSibling()) {
    Optional<MinAndMaxContentSizes> child_minmax;
    if (NeedMinAndMaxContentSizesForContentContribution(node->Style())) {
      child_minmax = node->ComputeMinAndMaxContentSizes();
    }

    MinAndMaxContentSizes child_sizes =
        ComputeMinAndMaxContentContribution(node->Style(), child_minmax);

    sizes->min_content = std::max(sizes->min_content, child_sizes.min_content);
    sizes->max_content = std::max(sizes->max_content, child_sizes.max_content);
  }

  sizes->max_content = std::max(sizes->min_content, sizes->max_content);
  return true;
}

NGLogicalOffset NGBlockLayoutAlgorithm::CalculateRelativeOffset(
    const NGBoxFragment& fragment) {
  LayoutUnit inline_offset =
      border_and_padding_.inline_start + curr_child_margins_.inline_start;
  LayoutUnit block_offset = content_size_;
  if (fragment.BfcOffset()) {
    block_offset = fragment.BfcOffset().value().block_offset -
                   builder_->BfcOffset().value().block_offset;
  }
  return {inline_offset, block_offset};
}

NGPhysicalFragment* NGBlockLayoutAlgorithm::Layout() {
  WTF::Optional<MinAndMaxContentSizes> sizes;
  if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) {
    // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return
    // MinAndMaxContentSizes.
    sizes = MinAndMaxContentSizes();
    ComputeMinAndMaxContentSizes(&*sizes);
  }

  border_and_padding_ =
      ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style());

  LayoutUnit inline_size =
      ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes);
  LayoutUnit adjusted_inline_size =
      inline_size - border_and_padding_.InlineSum();
  // TODO(layout-ng): For quirks mode, should we pass blockSize instead of
  // -1?
  LayoutUnit block_size =
      ComputeBlockSizeForFragment(ConstraintSpace(), Style(), NGSizeIndefinite);
  LayoutUnit adjusted_block_size(block_size);
  // Our calculated block-axis size may be indefinite at this point.
  // If so, just leave the size as NGSizeIndefinite instead of subtracting
  // borders and padding.
  if (adjusted_block_size != NGSizeIndefinite)
    adjusted_block_size -= border_and_padding_.BlockSum();

  space_builder_ = new NGConstraintSpaceBuilder(constraint_space_);
  if (Style().specifiesColumns()) {
    space_builder_->SetFragmentationType(kFragmentColumn);
    adjusted_inline_size =
        ResolveUsedColumnInlineSize(adjusted_inline_size, Style());
    LayoutUnit inline_progression =
        adjusted_inline_size + ResolveUsedColumnGap(Style());
    fragmentainer_mapper_ =
        new NGColumnMapper(inline_progression, adjusted_block_size);
  }
  space_builder_->SetAvailableSize(
      NGLogicalSize(adjusted_inline_size, adjusted_block_size));
  space_builder_->SetPercentageResolutionSize(
      NGLogicalSize(adjusted_inline_size, adjusted_block_size));

  builder_->SetDirection(constraint_space_->Direction());
  builder_->SetWritingMode(constraint_space_->WritingMode());
  builder_->SetInlineSize(inline_size).SetBlockSize(block_size);

  // TODO(glebl): fix multicol after the new margin collapsing/floats algorithm
  // based on BFCOffset is checked in.
  if (NGBlockBreakToken* token = CurrentBlockBreakToken()) {
    // Resume after a previous break.
    content_size_ = token->BreakOffset();
    current_child_ = token->InputNode();
  } else {
    content_size_ = border_and_padding_.block_start;
    current_child_ = first_child_;
  }

  curr_margin_strut_ = ConstraintSpace().MarginStrut();
  curr_bfc_offset_ = ConstraintSpace().BfcOffset();

  // Margins collapsing:
  //   Do not collapse margins between parent and its child if there is
  //   border/padding between them.
  if (border_and_padding_.block_start) {
    curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
    builder_->SetBfcOffset(curr_bfc_offset_);
    curr_margin_strut_ = NGMarginStrut();
  }
  curr_bfc_offset_.block_offset += content_size_;

  while (current_child_) {
    EPosition position = current_child_->Style().position();
    if (position == AbsolutePosition || position == FixedPosition) {
      builder_->AddOutOfFlowChildCandidate(current_child_,
                                           GetChildSpaceOffset());
      current_child_ = current_child_->NextSibling();
      continue;
    }

    DCHECK(!ConstraintSpace().HasBlockFragmentation() ||
           SpaceAvailableForCurrentChild() > LayoutUnit());
    space_for_current_child_ = CreateConstraintSpaceForCurrentChild();

    NGPhysicalFragment* child_fragment =
        current_child_->Layout(space_for_current_child_);

    FinishCurrentChildLayout(new NGBoxFragment(
        ConstraintSpace().WritingMode(), ConstraintSpace().Direction(),
        toNGPhysicalBoxFragment(child_fragment)));

    if (!ProceedToNextUnfinishedSibling(child_fragment))
      break;
  }

  // Margins collapsing:
  //   Bottom margins of an in-flow block box doesn't collapse with its last
  //   in-flow block-level child's bottom margin if the box has bottom
  //   border/padding.
  content_size_ += border_and_padding_.block_end;
  if (border_and_padding_.block_end ||
      ConstraintSpace().IsNewFormattingContext()) {
    content_size_ += curr_margin_strut_.Sum();
    curr_margin_strut_ = NGMarginStrut();
  }

  // Recompute the block-axis size now that we know our content size.
  block_size =
      ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
  builder_->SetBlockSize(block_size);

  // Layout our absolute and fixed positioned children.
  NGOutOfFlowLayoutPart(Style(), builder_).Run();

  // Non empty blocks always know their position in space:
  if (block_size) {
    curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
    UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(), builder_);
    PositionPendingFloats(curr_bfc_offset_, builder_);
  }

  // Margins collapsing:
  //   Do not collapse margins between the last in-flow child and bottom margin
  //   of its parent if the parent has height != auto()
  if (!Style().logicalHeight().isAuto()) {
    // TODO(glebl): handle minLogicalHeight, maxLogicalHeight.
    curr_margin_strut_ = NGMarginStrut();
  }
  builder_->SetEndMarginStrut(curr_margin_strut_);

  builder_->SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_);

  if (ConstraintSpace().HasBlockFragmentation())
    FinalizeForFragmentation();

  NGPhysicalFragment* fragment = builder_->ToBoxFragment();

  return fragment;
}

void NGBlockLayoutAlgorithm::FinishCurrentChildLayout(
    NGFragment* base_fragment) {
  const NGBoxFragment& fragment = *toNGBoxFragment(base_fragment);
  if (!fragment.PhysicalFragment()->UnpositionedFloats().isEmpty())
    DCHECK(!builder_->BfcOffset()) << "Parent BFC offset shouldn't be set here";
  // Pull out unpositioned floats to the current fragment. This may needed if
  // for example the child fragment could not position its floats because it's
  // empty and therefore couldn't determine its position in space.
  builder_->MutableUnpositionedFloats().appendVector(
      fragment.PhysicalFragment()->UnpositionedFloats());

  if (CurrentChildStyle().isFloating()) {
    NGFloatingObject* floating_object = new NGFloatingObject(
        fragment.PhysicalFragment(), space_for_current_child_, current_child_,
        CurrentChildStyle(), curr_child_margins_);
    builder_->AddUnpositionedFloat(floating_object);
    // No need to postpone the positioning if we know the correct offset.
    if (builder_->BfcOffset()) {
      NGLogicalOffset origin_point = curr_bfc_offset_;
      // Adjust origin point to the margins of the last child.
      // Example: <div style="margin-bottom: 20px"><float></div>
      //          <div style="margin-bottom: 30px"></div>
      origin_point.block_offset += curr_margin_strut_.Sum();
      PositionPendingFloats(origin_point, builder_);
    }
    return;
  }

  // Fragment that knows its offset can be used to set parent's BFC position.
  if (fragment.BfcOffset()) {
    curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset;
    UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(), builder_);
    PositionPendingFloats(curr_bfc_offset_, builder_);
  }
  NGLogicalOffset fragment_offset = CalculateRelativeOffset(fragment);

  if (fragmentainer_mapper_)
    fragmentainer_mapper_->ToVisualOffset(fragment_offset);
  else
    fragment_offset.block_offset -= PreviousBreakOffset();

  builder_->AddChild(base_fragment, fragment_offset);

  // Update margin strut.
  curr_margin_strut_ = fragment.EndMarginStrut();
  curr_margin_strut_.Append(curr_child_margins_.block_end);

  content_size_ = fragment.BlockSize() + fragment_offset.block_offset;
  max_inline_size_ =
      std::max(max_inline_size_, fragment.InlineSize() +
                                     curr_child_margins_.InlineSum() +
                                     border_and_padding_.InlineSum());
}

bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling(
    NGPhysicalFragment* child_fragment) {
  DCHECK(current_child_);
  NGBlockNode* finished_child = current_child_;
  current_child_ = current_child_->NextSibling();
  if (!ConstraintSpace().HasBlockFragmentation() && !fragmentainer_mapper_)
    return true;
  // If we're resuming layout after a fragmentainer break, we need to skip
  // siblings that we're done with. We may have been able to fully lay out some
  // node(s) preceding a node that we had to break inside (and therefore were
  // not able to fully lay out). This happens when we have parallel flows [1],
  // which are caused by floats, overflow, etc.
  //
  // [1] https://drafts.csswg.org/css-break/#parallel-flows
  if (CurrentBlockBreakToken()) {
    // TODO(layout-ng): Figure out if we need a better way to determine if the
    // node is finished. Maybe something to encode in a break token?
    while (current_child_ && current_child_->IsLayoutFinished())
      current_child_ = current_child_->NextSibling();
  }
  LayoutUnit break_offset = NextBreakOffset();
  bool is_out_of_space = content_size_ - PreviousBreakOffset() >= break_offset;
  if (!HasPendingBreakToken()) {
    bool child_broke = child_fragment->BreakToken();
    // This block needs to break if the child broke, or if we're out of space
    // and there's more content waiting to be laid out. Otherwise, just bail
    // now.
    if (!child_broke && (!is_out_of_space || !current_child_))
      return true;
    // Prepare a break token for this block, so that we know where to resume
    // when the time comes for that. We may not be able to abort layout of this
    // block right away, due to the posibility of parallel flows. We can only
    // abort when we're out of space, or when there are no siblings left to
    // process.
    NGBlockBreakToken* token;
    if (child_broke) {
      // The child we just laid out was the first one to break. So that is
      // where we need to resume.
      token = new NGBlockBreakToken(finished_child, break_offset);
    } else {
      // Resume layout at the next sibling that needs layout.
      DCHECK(current_child_);
      token = new NGBlockBreakToken(current_child_, break_offset);
    }
    SetPendingBreakToken(token);
  }

  if (!fragmentainer_mapper_) {
    if (!is_out_of_space)
      return true;
    // We have run out of space in this flow, so there's no work left to do for
    // this block in this fragmentainer. We should finalize the fragment and get
    // back to the remaining content when laying out the next fragmentainer(s).
    return false;
  }

  if (is_out_of_space || !current_child_) {
    NGBlockBreakToken* token = fragmentainer_mapper_->Advance();
    DCHECK(token || !is_out_of_space);
    if (token) {
      break_token_ = token;
      content_size_ = token->BreakOffset();
      current_child_ = token->InputNode();
    }
  }
  return true;
}

void NGBlockLayoutAlgorithm::SetPendingBreakToken(NGBlockBreakToken* token) {
  if (fragmentainer_mapper_)
    fragmentainer_mapper_->SetBreakToken(token);
  else
    builder_->SetBreakToken(token);
}

bool NGBlockLayoutAlgorithm::HasPendingBreakToken() const {
  if (fragmentainer_mapper_)
    return fragmentainer_mapper_->HasBreakToken();
  return builder_->HasBreakToken();
}

void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
  LayoutUnit block_size =
      ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
  LayoutUnit previous_break_offset = PreviousBreakOffset();
  block_size -= previous_break_offset;
  block_size = std::max(LayoutUnit(), block_size);
  LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable();
  DCHECK_GE(space_left, LayoutUnit());
  if (builder_->HasBreakToken()) {
    // A break token is ready, which means that we're going to break
    // before or inside a block-level child.
    builder_->SetBlockSize(std::min(space_left, block_size));
    builder_->SetBlockOverflow(space_left);
    return;
  }
  if (block_size > space_left) {
    // Need a break inside this block.
    builder_->SetBreakToken(new NGBlockBreakToken(nullptr, NextBreakOffset()));
    builder_->SetBlockSize(space_left);
    builder_->SetBlockOverflow(space_left);
    return;
  }
  // The end of the block fits in the current fragmentainer.
  builder_->SetBlockSize(block_size);
  builder_->SetBlockOverflow(content_size_ - previous_break_offset);
}

NGBlockBreakToken* NGBlockLayoutAlgorithm::CurrentBlockBreakToken() const {
  NGBreakToken* token = break_token_;
  if (!token || token->Type() != NGBreakToken::kBlockBreakToken)
    return nullptr;
  return toNGBlockBreakToken(token);
}

LayoutUnit NGBlockLayoutAlgorithm::PreviousBreakOffset() const {
  const NGBlockBreakToken* token = CurrentBlockBreakToken();
  return token ? token->BreakOffset() : LayoutUnit();
}

LayoutUnit NGBlockLayoutAlgorithm::NextBreakOffset() const {
  if (fragmentainer_mapper_)
    return fragmentainer_mapper_->NextBreakOffset();
  DCHECK(ConstraintSpace().HasBlockFragmentation());
  return PreviousBreakOffset() +
         ConstraintSpace().FragmentainerSpaceAvailable();
}

LayoutUnit NGBlockLayoutAlgorithm::SpaceAvailableForCurrentChild() const {
  LayoutUnit space_left;
  if (fragmentainer_mapper_)
    space_left = fragmentainer_mapper_->BlockSize();
  else if (ConstraintSpace().HasBlockFragmentation())
    space_left = ConstraintSpace().FragmentainerSpaceAvailable();
  else
    return NGSizeIndefinite;
  space_left -= BorderEdgeForCurrentChild() - PreviousBreakOffset();
  return space_left;
}

NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
    const NGConstraintSpace& space,
    const ComputedStyle& style) {
  WTF::Optional<MinAndMaxContentSizes> sizes;
  if (NeedMinAndMaxContentSizes(space, style)) {
    // TODO(ikilpatrick): Change ComputeMinAndMaxContentSizes to return
    // MinAndMaxContentSizes.
    sizes = current_child_->ComputeMinAndMaxContentSizes();
  }
  LayoutUnit child_inline_size =
      ComputeInlineSizeForFragment(space, style, sizes);
  NGBoxStrut margins =
      ComputeMargins(space, style, space.WritingMode(), space.Direction());
  if (!style.isFloating()) {
    ApplyAutoMargins(space, style, child_inline_size, &margins);
  }
  return margins;
}

NGConstraintSpace*
NGBlockLayoutAlgorithm::CreateConstraintSpaceForCurrentChild() {
  // TODO(layout-ng): Orthogonal children should also shrink to fit (in *their*
  // inline axis)
  bool shrink_to_fit = CurrentChildStyle().display() == EDisplay::InlineBlock ||
                       CurrentChildStyle().isFloating();
  DCHECK(current_child_);
  bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild(
      ConstraintSpace(), CurrentChildStyle());
  space_builder_->SetIsNewFormattingContext(is_new_bfc)
      .SetIsShrinkToFit(shrink_to_fit)
      .SetWritingMode(
          FromPlatformWritingMode(CurrentChildStyle().getWritingMode()))
      .SetTextDirection(CurrentChildStyle().direction());
  LayoutUnit space_available = SpaceAvailableForCurrentChild();
  space_builder_->SetFragmentainerSpaceAvailable(space_available);

  curr_child_margins_ = CalculateMargins(*space_builder_->ToConstraintSpace(),
                                         CurrentChildStyle());

  // Clearance :
  // - Collapse margins
  // - Update curr_bfc_offset and parent BFC offset if needed.
  // - Position all pending floats as position is known now.
  // TODO(glebl): Fix the use case with clear: left and an intruding right.
  // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847
  if (CurrentChildStyle().clear() != EClear::kNone) {
    curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
    UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(), builder_);
    // Only collapse margins if it's an adjoining block with clearance.
    if (!content_size_) {
      curr_margin_strut_ = NGMarginStrut();
      curr_child_margins_.block_start = LayoutUnit();
    }
    PositionPendingFloats(curr_bfc_offset_, builder_);
    AdjustToClearance(constraint_space_->Exclusions(), CurrentChildStyle(),
                      builder_->BfcOffset().value(), &content_size_);
  }

  // Append the current margin strut with child's block start margin.
  // Non empty border/padding use cases are handled inside of the child's
  // layout.
  curr_margin_strut_.Append(curr_child_margins_.block_start);
  space_builder_->SetMarginStrut(curr_margin_strut_);

  // Set estimated BFC offset to the next child's constraint space.
  curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value()
                                           : ConstraintSpace().BfcOffset();
  curr_bfc_offset_.block_offset += content_size_;
  curr_bfc_offset_.inline_offset += border_and_padding_.inline_start;
  if (ConstraintSpace().IsNewFormattingContext()) {
    curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start;
  }
  space_builder_->SetBfcOffset(curr_bfc_offset_);

  return space_builder_->ToConstraintSpace();
}

}  // namespace blink
