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

#include "core/layout/LayoutBlockFlow.h"
#include "core/layout/LayoutMultiColumnFlowThread.h"
#include "core/layout/LayoutMultiColumnSet.h"
#include "core/layout/api/LineLayoutAPIShim.h"
#include "core/layout/line/InlineIterator.h"
#include "core/layout/ng/layout_ng_block_flow.h"
#include "core/layout/ng/ng_block_break_token.h"
#include "core/layout/ng/ng_block_layout_algorithm.h"
#include "core/layout/ng/ng_box_fragment.h"
#include "core/layout/ng/ng_column_layout_algorithm.h"
#include "core/layout/ng/ng_constraint_space.h"
#include "core/layout/ng/ng_constraint_space_builder.h"
#include "core/layout/ng/ng_fragment_builder.h"
#include "core/layout/ng/ng_inline_node.h"
#include "core/layout/ng/ng_layout_result.h"
#include "core/layout/ng/ng_length_utils.h"
#include "core/layout/ng/ng_min_max_content_size.h"
#include "core/layout/ng/ng_writing_mode.h"
#include "core/paint/PaintLayer.h"
#include "platform/RuntimeEnabledFeatures.h"

namespace blink {

namespace {

RefPtr<NGLayoutResult> LayoutWithAlgorithm(const ComputedStyle& style,
                                           NGBlockNode* node,
                                           NGConstraintSpace* space,
                                           NGBreakToken* break_token) {
  if (style.specifiesColumns())
    return NGColumnLayoutAlgorithm(node, space,
                                   toNGBlockBreakToken(break_token))
        .Layout();
  return NGBlockLayoutAlgorithm(node, space, toNGBlockBreakToken(break_token))
      .Layout();
}

// Copies data back to the legacy layout tree for a given child fragment.
void FragmentPositionUpdated(const NGPhysicalFragment& fragment) {
  LayoutBox* layout_box = toLayoutBox(fragment.GetLayoutObject());
  if (!layout_box)
    return;

  DCHECK(layout_box->parent()) << "Should be called on children only.";

  // LegacyLayout flips vertical-rl horizontal coordinates before paint.
  // NGLayout flips X location for LegacyLayout compatibility.
  LayoutBlock* containing_block = layout_box->containingBlock();
  if (containing_block->styleRef().isFlippedBlocksWritingMode()) {
    LayoutUnit container_width = containing_block->size().width();
    layout_box->setX(container_width - fragment.LeftOffset() -
                     fragment.Width());
  } else {
    layout_box->setX(fragment.LeftOffset());
  }
  layout_box->setY(fragment.TopOffset());
}

// Similar to FragmentPositionUpdated but for floats.
// - Updates layout object's geometric information.
// - Creates legacy FloatingObject and attached it to the provided parent.
void FloatingObjectPositionedUpdated(NGFloatingObject* ng_floating_object,
                                     LayoutBox* parent) {
  NGPhysicalBoxFragment* box_fragment =
      toNGPhysicalBoxFragment(ng_floating_object->fragment.get());
  FragmentPositionUpdated(*box_fragment);

  LayoutBox* layout_box = toLayoutBox(box_fragment->GetLayoutObject());
  DCHECK(layout_box->isFloating());

  if (parent && parent->isLayoutBlockFlow()) {
    FloatingObject* floating_object =
        toLayoutBlockFlow(parent)->insertFloatingObject(*layout_box);
    floating_object->setIsInPlacedTree(false);
    floating_object->setX(ng_floating_object->left_offset);
    floating_object->setY(box_fragment->TopOffset());
    floating_object->setIsPlaced(true);
    floating_object->setIsInPlacedTree(true);
  }
}

void UpdateLegacyMultiColumnFlowThread(LayoutBox* layout_box,
                                       const NGPhysicalBoxFragment* fragment) {
  LayoutBlockFlow* multicol = toLayoutBlockFlow(layout_box);
  LayoutMultiColumnFlowThread* flow_thread = multicol->multiColumnFlowThread();
  if (!flow_thread)
    return;
  if (LayoutMultiColumnSet* column_set = flow_thread->firstMultiColumnSet()) {
    column_set->setWidth(fragment->Width());
    column_set->setHeight(fragment->Height());

    // TODO(mstensho): This value has next to nothing to do with the flow thread
    // portion size, but at least it's usually better than zero.
    column_set->endFlow(fragment->Height());

    column_set->clearNeedsLayout();
  }
  // TODO(mstensho): Fix the relatively nonsensical values here (the content box
  // size of the multicol container has very little to do with the price of
  // eggs).
  flow_thread->setWidth(fragment->Width());
  flow_thread->setHeight(fragment->Height());

  flow_thread->validateColumnSets();
  flow_thread->clearNeedsLayout();
}

}  // namespace

NGBlockNode::NGBlockNode(LayoutObject* layout_object)
    : NGLayoutInputNode(NGLayoutInputNodeType::kLegacyBlock),
      layout_box_(toLayoutBox(layout_object)) {
  DCHECK(layout_box_);
}

// Need an explicit destructor in the .cc file, or the MSWIN compiler will
// produce an error when attempting to generate a default one, if the .h file is
// included from a compilation unit that lacks the ComputedStyle definition.
NGBlockNode::~NGBlockNode() {}

RefPtr<NGLayoutResult> NGBlockNode::Layout(NGConstraintSpace* constraint_space,
                                           NGBreakToken* break_token) {
  // Use the old layout code and synthesize a fragment.
  if (!CanUseNewLayout()) {
    return RunOldLayout(*constraint_space);
  }

  RefPtr<NGLayoutResult> layout_result =
      LayoutWithAlgorithm(Style(), this, constraint_space, break_token);

  CopyFragmentDataToLayoutBox(*constraint_space, layout_result.get());
  return layout_result;
}

MinMaxContentSize NGBlockNode::ComputeMinMaxContentSize() {
  MinMaxContentSize sizes;
  if (!CanUseNewLayout()) {
    // TODO(layout-ng): This could be somewhat optimized by directly calling
    // computeIntrinsicLogicalWidths, but that function is currently private.
    // Consider doing that if this becomes a performance issue.
    LayoutUnit borderAndPadding = layout_box_->borderAndPaddingLogicalWidth();
    sizes.min_content = layout_box_->computeLogicalWidthUsing(
                            MainOrPreferredSize, Length(MinContent),
                            LayoutUnit(), layout_box_->containingBlock()) -
                        borderAndPadding;
    sizes.max_content = layout_box_->computeLogicalWidthUsing(
                            MainOrPreferredSize, Length(MaxContent),
                            LayoutUnit(), layout_box_->containingBlock()) -
                        borderAndPadding;
    return sizes;
  }

  RefPtr<NGConstraintSpace> constraint_space =
      NGConstraintSpaceBuilder(
          FromPlatformWritingMode(Style().getWritingMode()))
          .SetTextDirection(Style().direction())
          .ToConstraintSpace(FromPlatformWritingMode(Style().getWritingMode()));

  // TODO(cbiesinger): For orthogonal children, we need to always synthesize.
  NGBlockLayoutAlgorithm minmax_algorithm(this, constraint_space.get());
  Optional<MinMaxContentSize> maybe_sizes =
      minmax_algorithm.ComputeMinMaxContentSize();
  if (maybe_sizes.has_value())
    return *maybe_sizes;

  // Have to synthesize this value.
  RefPtr<NGLayoutResult> layout_result = Layout(constraint_space.get());
  NGPhysicalFragment* physical_fragment =
      layout_result->PhysicalFragment().get();
  NGBoxFragment min_fragment(FromPlatformWritingMode(Style().getWritingMode()),
                             toNGPhysicalBoxFragment(physical_fragment));
  sizes.min_content = min_fragment.InlineOverflow();

  // Now, redo with infinite space for max_content
  constraint_space =
      NGConstraintSpaceBuilder(
          FromPlatformWritingMode(Style().getWritingMode()))
          .SetTextDirection(Style().direction())
          .SetAvailableSize({LayoutUnit::max(), LayoutUnit()})
          .SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()})
          .ToConstraintSpace(FromPlatformWritingMode(Style().getWritingMode()));

  layout_result = Layout(constraint_space.get());
  physical_fragment = layout_result->PhysicalFragment().get();
  NGBoxFragment max_fragment(FromPlatformWritingMode(Style().getWritingMode()),
                             toNGPhysicalBoxFragment(physical_fragment));
  sizes.max_content = max_fragment.InlineOverflow();
  return sizes;
}

const ComputedStyle& NGBlockNode::Style() const {
  return layout_box_->styleRef();
}

NGLayoutInputNode* NGBlockNode::NextSibling() {
  if (!next_sibling_) {
    LayoutObject* next_sibling = layout_box_->nextSibling();
    if (next_sibling) {
      if (next_sibling->isInline()) {
        next_sibling_ = new NGInlineNode(
            next_sibling, toLayoutBlockFlow(layout_box_->parent()));
      } else {
        next_sibling_ = new NGBlockNode(next_sibling);
      }
    }
  }
  return next_sibling_;
}

LayoutObject* NGBlockNode::GetLayoutObject() {
  return layout_box_;
}

NGLayoutInputNode* NGBlockNode::FirstChild() {
  if (!first_child_) {
    LayoutObject* child = layout_box_->slowFirstChild();
    if (child) {
      if (child->isInline()) {
        first_child_ = new NGInlineNode(child, toLayoutBlockFlow(layout_box_));
      } else {
        first_child_ = new NGBlockNode(child);
      }
    }
  }
  return first_child_;
}

DEFINE_TRACE(NGBlockNode) {
  visitor->trace(next_sibling_);
  visitor->trace(first_child_);
  NGLayoutInputNode::trace(visitor);
}

bool NGBlockNode::CanUseNewLayout() {
  if (!layout_box_->isLayoutBlockFlow())
    return false;
  return RuntimeEnabledFeatures::layoutNGEnabled() || !HasInlineChildren();
}

bool NGBlockNode::HasInlineChildren() {
  if (!layout_box_->isLayoutBlockFlow())
    return false;

  const LayoutBlockFlow* block_flow = toLayoutBlockFlow(layout_box_);
  if (!block_flow->childrenInline())
    return false;
  LayoutObject* child = block_flow->firstChild();
  while (child) {
    if (child->isInline())
      return true;
    child = child->nextSibling();
  }

  return false;
}

void NGBlockNode::CopyFragmentDataToLayoutBox(
    const NGConstraintSpace& constraint_space,
    NGLayoutResult* layout_result) {
  NGPhysicalBoxFragment* fragment =
      toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get());

  if (layout_box_->style()->specifiesColumns())
    UpdateLegacyMultiColumnFlowThread(layout_box_, fragment);
  layout_box_->setWidth(fragment->Width());
  layout_box_->setHeight(fragment->Height());
  NGBoxStrut border_and_padding = ComputeBorders(constraint_space, Style()) +
                                  ComputePadding(constraint_space, Style());
  LayoutUnit intrinsic_logical_height =
      layout_box_->style()->isHorizontalWritingMode()
          ? fragment->HeightOverflow()
          : fragment->WidthOverflow();
  intrinsic_logical_height -= border_and_padding.BlockSum();
  layout_box_->setIntrinsicContentLogicalHeight(intrinsic_logical_height);

  // We may still have unpositioned floats when we reach the root box.
  if (!layout_box_->parent()) {
    for (const RefPtr<NGFloatingObject>& floating_object :
         fragment->PositionedFloats()) {
      FloatingObjectPositionedUpdated(floating_object.get(), layout_box_);
    }
  }

  for (const auto& child_fragment : fragment->Children()) {
    if (child_fragment->IsPlaced())
      FragmentPositionUpdated(toNGPhysicalBoxFragment(*child_fragment));

    for (const RefPtr<NGFloatingObject>& floating_object :
         toNGPhysicalBoxFragment(child_fragment.get())->PositionedFloats()) {
      FloatingObjectPositionedUpdated(
          floating_object.get(),
          toLayoutBox(child_fragment->GetLayoutObject()));
    }
  }

  if (layout_box_->isLayoutBlock())
    toLayoutBlock(layout_box_)->layoutPositionedObjects(true);
  layout_box_->clearNeedsLayout();
  if (layout_box_->isLayoutBlockFlow()) {
    toLayoutBlockFlow(layout_box_)->updateIsSelfCollapsing();
  }
}

RefPtr<NGLayoutResult> NGBlockNode::RunOldLayout(
    const NGConstraintSpace& constraint_space) {
  NGLogicalSize available_size = constraint_space.PercentageResolutionSize();
  LayoutObject* containing_block = layout_box_->containingBlock();
  bool parallel_writing_mode;
  if (!containing_block) {
    parallel_writing_mode = true;
  } else {
    parallel_writing_mode = IsParallelWritingMode(
        FromPlatformWritingMode(containing_block->styleRef().getWritingMode()),
        FromPlatformWritingMode(Style().getWritingMode()));
  }
  if (parallel_writing_mode) {
    layout_box_->setOverrideContainingBlockContentLogicalWidth(
        available_size.inline_size);
    layout_box_->setOverrideContainingBlockContentLogicalHeight(
        available_size.block_size);
  } else {
    // OverrideContainingBlock should be in containing block writing mode.
    layout_box_->setOverrideContainingBlockContentLogicalWidth(
        available_size.block_size);
    layout_box_->setOverrideContainingBlockContentLogicalHeight(
        available_size.inline_size);
  }
  // TODO(layout-ng): Does this handle scrollbars correctly?
  if (constraint_space.IsFixedSizeInline()) {
    layout_box_->setOverrideLogicalContentWidth(
        constraint_space.AvailableSize().inline_size -
        layout_box_->borderAndPaddingLogicalWidth());
  }
  if (constraint_space.IsFixedSizeBlock()) {
    layout_box_->setOverrideLogicalContentHeight(
        constraint_space.AvailableSize().block_size -
        layout_box_->borderAndPaddingLogicalHeight());
  }

  if (layout_box_->isLayoutNGBlockFlow() && layout_box_->needsLayout()) {
    toLayoutNGBlockFlow(layout_box_)->LayoutBlockFlow::layoutBlock(true);
  } else {
    layout_box_->forceLayout();
  }
  LayoutRect overflow = layout_box_->layoutOverflowRect();
  // TODO(layout-ng): This does not handle writing modes correctly (for
  // overflow)
  NGFragmentBuilder builder(NGPhysicalFragment::kFragmentBox, this);
  builder.SetInlineSize(layout_box_->logicalWidth())
      .SetBlockSize(layout_box_->logicalHeight())
      .SetDirection(layout_box_->styleRef().direction())
      .SetWritingMode(
          FromPlatformWritingMode(layout_box_->styleRef().getWritingMode()))
      .SetInlineOverflow(overflow.width())
      .SetBlockOverflow(overflow.height());
  return builder.ToBoxFragment();
}

void NGBlockNode::UseOldOutOfFlowPositioning() {
  DCHECK(layout_box_->isOutOfFlowPositioned());
  layout_box_->containingBlock()->insertPositionedObject(layout_box_);
}

// Save static position for legacy AbsPos layout.
void NGBlockNode::SaveStaticOffsetForLegacy(const NGLogicalOffset& offset) {
  DCHECK(layout_box_->isOutOfFlowPositioned());
  DCHECK(layout_box_->layer());
  layout_box_->layer()->setStaticBlockPosition(offset.block_offset);
  layout_box_->layer()->setStaticInlinePosition(offset.inline_offset);
}

}  // namespace blink
