// 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);
    DCHECK(unpositioned_float->layout_result->PhysicalFragment());
    return NGFragment(parent_space.WritingMode(),
                      *unpositioned_float->layout_result->PhysicalFragment())
        .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);

  DCHECK(unpositioned_float->layout_result->PhysicalFragment());
  const auto& fragment = *unpositioned_float->layout_result->PhysicalFragment();

  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());
  }

  DCHECK(layout_result->PhysicalFragment());
  NGFragment float_fragment(parent_space.WritingMode(),
                            *layout_result->PhysicalFragment());

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