// 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_container_fragment_builder.h"

#include "core/layout/ng/ng_exclusion_space.h"
#include "core/layout/ng/ng_layout_result.h"
#include "core/layout/ng/ng_physical_fragment.h"
#include "core/layout/ng/ng_unpositioned_float.h"
#include "core/style/ComputedStyle.h"

namespace blink {

NGContainerFragmentBuilder::NGContainerFragmentBuilder(
    scoped_refptr<const ComputedStyle> style,
    NGWritingMode writing_mode,
    TextDirection direction)
    : NGBaseFragmentBuilder(std::move(style), writing_mode, direction) {}

NGContainerFragmentBuilder::~NGContainerFragmentBuilder() {}

NGContainerFragmentBuilder& NGContainerFragmentBuilder::SetInlineSize(
    LayoutUnit inline_size) {
  DCHECK_GE(inline_size, LayoutUnit());
  inline_size_ = inline_size;
  return *this;
}

NGContainerFragmentBuilder& NGContainerFragmentBuilder::SetBfcOffset(
    const NGBfcOffset& bfc_offset) {
  bfc_offset_ = bfc_offset;
  return *this;
}

NGContainerFragmentBuilder& NGContainerFragmentBuilder::SetEndMarginStrut(
    const NGMarginStrut& end_margin_strut) {
  end_margin_strut_ = end_margin_strut;
  return *this;
}

NGContainerFragmentBuilder& NGContainerFragmentBuilder::SetExclusionSpace(
    std::unique_ptr<const NGExclusionSpace> exclusion_space) {
  exclusion_space_ = std::move(exclusion_space);
  return *this;
}

NGContainerFragmentBuilder& NGContainerFragmentBuilder::SwapUnpositionedFloats(
    Vector<scoped_refptr<NGUnpositionedFloat>>* unpositioned_floats) {
  unpositioned_floats_.swap(*unpositioned_floats);
  return *this;
}

NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
    scoped_refptr<NGLayoutResult> child,
    const NGLogicalOffset& child_offset) {
  // Collect the child's out of flow descendants.
  // child_offset is offset of inline_start/block_start vertex.
  // Candidates need offset of top/left vertex.
  const auto& ouf_of_flow_descendants = child->OutOfFlowPositionedDescendants();
  if (!ouf_of_flow_descendants.IsEmpty()) {
    NGLogicalOffset top_left_offset;
    NGPhysicalSize child_size = child->PhysicalFragment()->Size();
    switch (WritingMode()) {
      case kHorizontalTopBottom:
        top_left_offset =
            (IsRtl(Direction()))
                ? NGLogicalOffset{child_offset.inline_offset + child_size.width,
                                  child_offset.block_offset}
                : child_offset;
        break;
      case kVerticalRightLeft:
      case kSidewaysRightLeft:
        top_left_offset =
            (IsRtl(Direction()))
                ? NGLogicalOffset{child_offset.inline_offset +
                                      child_size.height,
                                  child_offset.block_offset + child_size.width}
                : NGLogicalOffset{child_offset.inline_offset,
                                  child_offset.block_offset + child_size.width};
        break;
      case kVerticalLeftRight:
      case kSidewaysLeftRight:
        top_left_offset = (IsRtl(Direction()))
                              ? NGLogicalOffset{child_offset.inline_offset +
                                                    child_size.height,
                                                child_offset.block_offset}
                              : child_offset;
        break;
    }
    for (const NGOutOfFlowPositionedDescendant& descendant :
         ouf_of_flow_descendants) {
      oof_positioned_candidates_.push_back(
          NGOutOfFlowPositionedCandidate{descendant, top_left_offset});
    }
  }

  return AddChild(child->PhysicalFragment(), child_offset);
}

NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
    scoped_refptr<NGPhysicalFragment> child,
    const NGLogicalOffset& child_offset) {
  children_.push_back(std::move(child));
  offsets_.push_back(child_offset);
  return *this;
}

NGContainerFragmentBuilder&
NGContainerFragmentBuilder::AddOutOfFlowChildCandidate(
    NGBlockNode child,
    const NGLogicalOffset& child_offset,
    Optional<TextDirection> direction) {
  DCHECK(child);

  oof_positioned_candidates_.push_back(NGOutOfFlowPositionedCandidate{
      NGOutOfFlowPositionedDescendant{
          child, NGStaticPosition::Create(WritingMode(),
                                          direction ? *direction : Direction(),
                                          NGPhysicalOffset())},
      child_offset});

  child.SaveStaticOffsetForLegacy(child_offset);
  return *this;
}

NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddOutOfFlowDescendant(
    NGOutOfFlowPositionedDescendant descendant) {
  oof_positioned_descendants_.push_back(descendant);
  return *this;
}

void NGContainerFragmentBuilder::GetAndClearOutOfFlowDescendantCandidates(
    Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates) {
  DCHECK(descendant_candidates->IsEmpty());

  descendant_candidates->ReserveCapacity(oof_positioned_candidates_.size());

  DCHECK_GE(inline_size_, LayoutUnit());
  DCHECK_GE(block_size_, LayoutUnit());
  NGPhysicalSize builder_physical_size{Size().ConvertToPhysical(WritingMode())};

  for (NGOutOfFlowPositionedCandidate& candidate : oof_positioned_candidates_) {
    NGPhysicalOffset child_offset = candidate.child_offset.ConvertToPhysical(
        WritingMode(), Direction(), builder_physical_size, NGPhysicalSize());

    NGStaticPosition builder_relative_position;
    builder_relative_position.type = candidate.descendant.static_position.type;
    builder_relative_position.offset =
        child_offset + candidate.descendant.static_position.offset;

    descendant_candidates->push_back(NGOutOfFlowPositionedDescendant{
        candidate.descendant.node, builder_relative_position});
  }

  // Clear our current canidate list. This may get modified again if the
  // current fragment is a containing block, and AddChild is called with a
  // descendant from this list.
  //
  // The descendant may be a "position: absolute" which contains a "position:
  // fixed" for example. (This fragment isn't the containing block for the
  // fixed descendant).
  oof_positioned_candidates_.clear();
}

}  // namespace blink
