// Copyright 2017 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_floats_utils.h"

#include "core/layout/MinMaxSize.h"
#include "core/layout/ng/ng_box_fragment.h"
#include "core/layout/ng/ng_constraint_space_builder.h"
#include "core/layout/ng/ng_layout_result.h"
#include "core/layout/ng/ng_length_utils.h"
#include "core/layout/ng/ng_positioned_float.h"
#include "core/layout/ng/ng_space_utils.h"
#include "core/style/ComputedStyle.h"

namespace blink {
namespace {

// 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.
NGBfcOffset AdjustToTopEdgeAlignmentRule(
    const NGExclusionSpace& exclusion_space,
    const NGBfcOffset& offset) {
  NGBfcOffset adjusted_offset = offset;
  adjusted_offset.block_offset = std::max(
      adjusted_offset.block_offset, exclusion_space.LastFloatBlockStart());

  return adjusted_offset;
}

NGLayoutOpportunity FindLayoutOpportunityForFloat(
    const NGBfcOffset& origin_offset,
    const NGExclusionSpace& exclusion_space,
    const NGUnpositionedFloat& unpositioned_float,
    LayoutUnit inline_size) {
  NGBfcOffset adjusted_origin_point =
      AdjustToTopEdgeAlignmentRule(exclusion_space, origin_offset);
  WTF::Optional<LayoutUnit> clearance_offset =
      exclusion_space.ClearanceOffset(unpositioned_float.ClearType());

  AdjustToClearance(clearance_offset, &adjusted_origin_point);

  NGLogicalSize float_size(inline_size + unpositioned_float.margins.InlineSum(),
                           LayoutUnit());
  // TODO(ikilpatrick): Don't include the block-start margin of a float which
  // has fragmented.
  return exclusion_space.FindLayoutOpportunity(
      adjusted_origin_point, unpositioned_float.available_size, float_size);
}

// Calculates the logical offset for opportunity.
NGLogicalOffset CalculateLogicalOffsetForOpportunity(
    const NGConstraintSpace& parent_space,
    const NGLayoutOpportunity& opportunity,
    const NGBfcOffset& float_margin_bfc_offset,
    const LayoutUnit parent_bfc_block_offset,
    const NGUnpositionedFloat* unpositioned_float,
    LayoutUnit parent_inline_size,
    LayoutUnit float_margin_box_inline_size) {
  DCHECK(unpositioned_float);
  auto margins = unpositioned_float->margins;

  // We need to respect the current text direction to calculate the logical
  // offset correctly.
  LayoutUnit relative_line_offset =
      float_margin_bfc_offset.line_offset - unpositioned_float->bfc_line_offset;

  LayoutUnit inline_offset = parent_space.Direction() == TextDirection::kLtr
                                 ? relative_line_offset + margins.inline_start
                                 : parent_inline_size - relative_line_offset -
                                       float_margin_box_inline_size +
                                       margins.inline_start;

  NGLogicalOffset offset = {inline_offset,
                            float_margin_bfc_offset.block_offset +
                                margins.block_start - parent_bfc_block_offset};

  return offset;
}

// Creates an exclusion from the fragment that will be placed in the provided
// layout opportunity.
NGExclusion CreateExclusion(const NGFragment& fragment,
                            const NGBfcOffset& float_margin_bfc_offset,
                            const NGBoxStrut& margins,
                            NGExclusion::Type exclusion_type) {
  NGExclusion exclusion;
  exclusion.type = exclusion_type;
  NGBfcRect& rect = exclusion.rect;
  rect.offset = float_margin_bfc_offset;

  // TODO(ikilpatrick): Don't include the block-start margin of a float which
  // has fragmented.
  rect.size.inline_size = fragment.InlineSize() + margins.InlineSum();
  rect.size.block_size = fragment.BlockSize() + margins.BlockSum();
  return exclusion;
}

// TODO(ikilpatrick): origin_block_offset looks wrong for fragmentation here.
WTF::Optional<LayoutUnit> CalculateFragmentationOffset(
    const LayoutUnit origin_block_offset,
    const NGUnpositionedFloat& unpositioned_float,
    const NGConstraintSpace& parent_space) {
  const ComputedStyle& style = unpositioned_float.node.Style();
  DCHECK(FromPlatformWritingMode(style.GetWritingMode()) ==
         parent_space.WritingMode());

  if (parent_space.HasBlockFragmentation()) {
    return parent_space.FragmentainerSpaceAvailable() - origin_block_offset;
  }

  return WTF::nullopt;
}

// Creates a constraint space for an unpositioned float.
RefPtr<NGConstraintSpace> CreateConstraintSpaceForFloat(
    const NGUnpositionedFloat& unpositioned_float,
    const NGConstraintSpace& parent_space,
    WTF::Optional<LayoutUnit> fragmentation_offset = WTF::nullopt) {
  const ComputedStyle& style = unpositioned_float.node.Style();

  NGConstraintSpaceBuilder builder(parent_space);

  if (fragmentation_offset) {
    builder.SetFragmentainerSpaceAvailable(fragmentation_offset.value())
        .SetFragmentationType(parent_space.BlockFragmentationType());
  } else {
    builder.SetFragmentationType(NGFragmentationType::kFragmentNone);
  }

  return builder.SetPercentageResolutionSize(unpositioned_float.percentage_size)
      .SetAvailableSize(unpositioned_float.available_size)
      .SetIsNewFormattingContext(true)
      .SetIsShrinkToFit(true)
      .SetTextDirection(style.Direction())
      .ToConstraintSpace(FromPlatformWritingMode(style.GetWritingMode()));
}

}  // namespace

LayoutUnit ComputeInlineSizeForUnpositionedFloat(
    const NGConstraintSpace& parent_space,
    NGUnpositionedFloat* unpositioned_float) {
  DCHECK(unpositioned_float);

  const ComputedStyle& style = unpositioned_float->node.Style();

  bool is_same_writing_mode = FromPlatformWritingMode(style.GetWritingMode()) ==
                              parent_space.WritingMode();

  // If we've already performed layout on the unpositioned float, just return
  // the cached value.
  if (unpositioned_float->layout_result) {
    DCHECK(!is_same_writing_mode);
    return NGFragment(
               parent_space.WritingMode(),
               unpositioned_float->layout_result->PhysicalFragment().Get())
        .InlineSize();
  }

  const RefPtr<NGConstraintSpace> space =
      CreateConstraintSpaceForFloat(*unpositioned_float, parent_space);

  // If the float has the same writing mode as the block formatting context we
  // shouldn't perform a full layout just yet. Our position may determine where
  // we fragment.
  if (is_same_writing_mode) {
    WTF::Optional<MinMaxSize> min_max_size;
    if (NeedMinMaxSize(*space.Get(), style))
      min_max_size = unpositioned_float->node.ComputeMinMaxSize();
    return ComputeInlineSizeForFragment(*space.Get(), style, min_max_size);
  }

  // If we are performing layout on a float to determine its inline size it
  // should never have fragmented.
  DCHECK(!unpositioned_float->token);

  // A float which has a different writing mode can't fragment, and we
  // (probably) need to perform a full layout in order to correctly determine
  // its inline size. We are able to cache this result on the
  // unpositioned_float at this stage.
  unpositioned_float->layout_result = unpositioned_float->node.Layout(*space);

  const NGPhysicalFragment* fragment =
      unpositioned_float->layout_result->PhysicalFragment().Get();

  DCHECK(fragment->BreakToken()->IsFinished());

  return NGFragment(parent_space.WritingMode(), fragment).InlineSize();
}

NGPositionedFloat PositionFloat(LayoutUnit origin_block_offset,
                                LayoutUnit parent_bfc_block_offset,
                                NGUnpositionedFloat* unpositioned_float,
                                const NGConstraintSpace& parent_space,
                                LayoutUnit parent_inline_size,
                                NGExclusionSpace* exclusion_space) {
  DCHECK(unpositioned_float);
  LayoutUnit inline_size =
      ComputeInlineSizeForUnpositionedFloat(parent_space, unpositioned_float);

  NGBfcOffset origin_offset = {unpositioned_float->origin_bfc_line_offset,
                               origin_block_offset};

  // Find a layout opportunity that will fit our float.
  NGLayoutOpportunity opportunity = FindLayoutOpportunityForFloat(
      origin_offset, *exclusion_space, *unpositioned_float, inline_size);

#if DCHECK_IS_ON()
  bool is_same_writing_mode =
      FromPlatformWritingMode(
          unpositioned_float->node.Style().GetWritingMode()) ==
      parent_space.WritingMode();
#endif

  RefPtr<NGLayoutResult> layout_result;
  // We should only have a fragment if its writing mode is different, i.e. it
  // can't fragment.
  if (unpositioned_float->layout_result) {
#if DCHECK_IS_ON()
    DCHECK(!is_same_writing_mode);
#endif
    layout_result = unpositioned_float->layout_result;
  } else {
#if DCHECK_IS_ON()
    DCHECK(is_same_writing_mode);
#endif
    WTF::Optional<LayoutUnit> fragmentation_offset =
        CalculateFragmentationOffset(origin_block_offset, *unpositioned_float,
                                     parent_space);

    RefPtr<NGConstraintSpace> space = CreateConstraintSpaceForFloat(
        *unpositioned_float, parent_space, fragmentation_offset);
    layout_result = unpositioned_float->node.Layout(
        *space, unpositioned_float->token.Get());
  }

  NGBoxFragment float_fragment(
      parent_space.WritingMode(),
      ToNGPhysicalBoxFragment(layout_result.Get()->PhysicalFragment().Get()));

  // TODO(glebl): This should check for infinite opportunity instead.
  if (opportunity.IsEmpty()) {
    // Because of the implementation specific of the layout opportunity iterator
    // an empty opportunity can mean 2 things:
    // - search for layout opportunities is exhausted.
    // - opportunity has an infinite size. That's because CS is infinite.
    opportunity = NGLayoutOpportunity(
        NGBfcOffset(),
        NGLogicalSize(float_fragment.InlineSize(), float_fragment.BlockSize()));
  }

  LayoutUnit float_margin_box_inline_size =
      float_fragment.InlineSize() + unpositioned_float->margins.InlineSum();

  // Calculate the float's margin box BFC offset.
  NGBfcOffset float_margin_bfc_offset = opportunity.offset;
  if (unpositioned_float->IsRight()) {
    float_margin_bfc_offset.line_offset +=
        (opportunity.size.inline_size - float_margin_box_inline_size);
  }

  // Add the float as an exclusion.
  const NGExclusion exclusion = CreateExclusion(
      float_fragment, float_margin_bfc_offset, unpositioned_float->margins,
      unpositioned_float->IsRight() ? NGExclusion::Type::kFloatRight
                                    : NGExclusion::Type::kFloatLeft);
  exclusion_space->Add(exclusion);

  NGLogicalOffset logical_offset = CalculateLogicalOffsetForOpportunity(
      parent_space, opportunity, float_margin_bfc_offset,
      parent_bfc_block_offset, unpositioned_float, parent_inline_size,
      float_margin_box_inline_size);

  return NGPositionedFloat(std::move(layout_result), logical_offset);
}

const Vector<NGPositionedFloat> PositionFloats(
    LayoutUnit origin_block_offset,
    LayoutUnit parent_bfc_block_offset,
    const Vector<RefPtr<NGUnpositionedFloat>>& unpositioned_floats,
    const NGConstraintSpace& space,
    LayoutUnit parent_inline_size,
    NGExclusionSpace* exclusion_space) {
  Vector<NGPositionedFloat> positioned_floats;
  positioned_floats.ReserveCapacity(unpositioned_floats.size());

  for (auto& unpositioned_float : unpositioned_floats) {
    positioned_floats.push_back(PositionFloat(
        origin_block_offset, parent_bfc_block_offset, unpositioned_float.Get(),
        space, parent_inline_size, exclusion_space));
  }

  return positioned_floats;
}

}  // namespace blink
