// 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/api/LineLayoutAPIShim.h"
#include "core/layout/line/InlineIterator.h"
#include "core/layout/ng/layout_ng_block_flow.h"
#include "core/layout/ng/ng_block_layout_algorithm.h"
#include "core/layout/ng/ng_constraint_space_builder.h"
#include "core/layout/ng/ng_constraint_space.h"
#include "core/layout/ng/ng_fragment.h"
#include "core/layout/ng/ng_fragment_builder.h"
#include "core/layout/ng/ng_inline_node.h"
#include "core/layout/ng/ng_layout_coordinator.h"
#include "core/layout/ng/ng_length_utils.h"
#include "core/layout/ng/ng_writing_mode.h"
#include "platform/RuntimeEnabledFeatures.h"

namespace blink {

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

NGBlockNode::NGBlockNode(ComputedStyle* style)
    : NGLayoutInputNode(NGLayoutInputNodeType::kLegacyBlock),
      layout_box_(nullptr),
      style_(style) {
  DCHECK(style_);
}

// 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() {}

bool NGBlockNode::Layout(NGConstraintSpace* constraint_space,
                         NGFragmentBase** out) {
  DCHECK(!minmax_algorithm_)
      << "Can't interleave Layout and ComputeMinAndMaxContentSizes";
  // We can either use the new layout code to do the layout and then copy the
  // resulting size to the LayoutObject, or use the old layout code and
  // synthesize a fragment.
  if (CanUseNewLayout()) {
    NGPhysicalFragmentBase* fragment;

    // Store a coordinator so Layout can preserve its existing semantic
    // of returning false until completed.
    if (!layout_coordinator_)
      layout_coordinator_ = new NGLayoutCoordinator(this, constraint_space);

    if (!layout_coordinator_->Tick(&fragment))
      return false;

    fragment_ = toNGPhysicalFragment(fragment);

    UpdateLayoutBox(fragment_, constraint_space);
  } else {
    DCHECK(layout_box_);
    fragment_ = RunOldLayout(*constraint_space);
  }
  *out = new NGFragment(FromPlatformWritingMode(Style()->getWritingMode()),
                        Style()->direction(), fragment_.get());
  // Reset coordinator for future use
  layout_coordinator_ = nullptr;
  return true;
}

void NGBlockNode::UpdateLayoutBox(NGPhysicalFragment* fragment,
                                  const NGConstraintSpace* constraint_space) {
  fragment_ = fragment;
  if (layout_box_) {
    CopyFragmentDataToLayoutBox(*constraint_space);
  }
}

bool NGBlockNode::ComputeMinAndMaxContentSizes(MinAndMaxContentSizes* sizes) {
  if (!CanUseNewLayout()) {
    DCHECK(layout_box_);
    // 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 true;
  }
  DCHECK(!layout_coordinator_)
      << "Can't interleave Layout and ComputeMinAndMaxContentSizes";

  NGConstraintSpace* constraint_space =
      NGConstraintSpaceBuilder(
          FromPlatformWritingMode(Style()->getWritingMode()))
          .SetTextDirection(Style()->direction())
          .ToConstraintSpace();

  if (!minmax_algorithm_) {
    minmax_algorithm_ = new NGBlockLayoutAlgorithm(
        Style(), toNGBlockNode(FirstChild()), constraint_space);
  }
  // TODO(cbiesinger): For orthogonal children, we need to always synthesize.
  NGLayoutAlgorithm::MinAndMaxState state =
      minmax_algorithm_->ComputeMinAndMaxContentSizes(sizes);
  if (state == NGLayoutAlgorithm::kSuccess) {
    minmax_algorithm_ = nullptr;
    return true;
  }
  if (state == NGLayoutAlgorithm::kPending)
    return false;
  DCHECK_EQ(state, NGLayoutAlgorithm::kNotImplemented);

  // TODO(cbiesinger): Replace the loops below with a state machine like in
  // Layout.

  NGLayoutCoordinator* minmax_coordinator =
      new NGLayoutCoordinator(this, constraint_space);

  // Have to synthesize this value.
  NGPhysicalFragmentBase* physical_fragment;
  while (!minmax_coordinator->Tick(&physical_fragment))
    continue;
  NGFragment* fragment = new NGFragment(
      FromPlatformWritingMode(Style()->getWritingMode()), Style()->direction(),
      toNGPhysicalFragment(physical_fragment));

  sizes->min_content = 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();

  minmax_coordinator = new NGLayoutCoordinator(this, constraint_space);
  while (!minmax_coordinator->Tick(&physical_fragment))
    continue;

  fragment = new NGFragment(FromPlatformWritingMode(Style()->getWritingMode()),
                            Style()->direction(),
                            toNGPhysicalFragment(physical_fragment));
  sizes->max_content = fragment->InlineOverflow();
  minmax_algorithm_ = nullptr;
  return true;
}

ComputedStyle* NGBlockNode::MutableStyle() {
  if (style_)
    return style_.get();
  DCHECK(layout_box_);
  return layout_box_->mutableStyle();
}

const ComputedStyle* NGBlockNode::Style() const {
  if (style_)
    return style_.get();
  DCHECK(layout_box_);
  return layout_box_->style();
}

NGBlockNode* NGBlockNode::NextSibling() {
  if (!next_sibling_) {
    LayoutObject* next_sibling =
        layout_box_ ? layout_box_->nextSibling() : nullptr;
    NGBlockNode* box = next_sibling ? new NGBlockNode(next_sibling) : nullptr;
    SetNextSibling(box);
  }
  return next_sibling_;
}

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

void NGBlockNode::SetNextSibling(NGBlockNode* sibling) {
  next_sibling_ = sibling;
}

void NGBlockNode::SetFirstChild(NGLayoutInputNode* child) {
  first_child_ = child;
}

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

void NGBlockNode::PositionUpdated() {
  if (!layout_box_)
    return;
  DCHECK(layout_box_->parent()) << "Should be called on children only.";

  layout_box_->setX(fragment_->LeftOffset());
  layout_box_->setY(fragment_->TopOffset());

  if (layout_box_->isFloating() && layout_box_->parent()->isLayoutBlockFlow()) {
    FloatingObject* floating_object = toLayoutBlockFlow(layout_box_->parent())
                                          ->insertFloatingObject(*layout_box_);
    floating_object->setX(fragment_->LeftOffset());
    floating_object->setY(fragment_->TopOffset());
    floating_object->setIsPlaced(true);
  }
}

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

bool NGBlockNode::HasInlineChildren() {
  if (!layout_box_ || !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) {
  DCHECK(layout_box_);
  layout_box_->setWidth(fragment_->Width());
  layout_box_->setHeight(fragment_->Height());
  NGBoxStrut border_and_padding =
      ComputeBorders(*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);

  // TODO(layout-dev): Currently we are not actually performing layout on
  // inline children. For now just clear the needsLayout bit so that we can
  // run unittests.
  if (HasInlineChildren()) {
    for (InlineWalker walker(
             LineLayoutBlockFlow(toLayoutBlockFlow(layout_box_)));
         !walker.atEnd(); walker.advance()) {
      LayoutObject* o = LineLayoutAPIShim::layoutObjectFrom(walker.current());
      o->clearNeedsLayout();
    }

    // Ensure the position of the children are copied across to the
    // LayoutObject tree.
  } else {
    for (NGBlockNode* box = toNGBlockNode(FirstChild()); box;
         box = box->NextSibling()) {
      if (box->fragment_)
        box->PositionUpdated();
    }
  }

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

NGPhysicalFragment* NGBlockNode::RunOldLayout(
    const NGConstraintSpace& constraint_space) {
  // TODO(layout-ng): If fixedSize is true, set the override width/height too
  NGLogicalSize available_size = constraint_space.AvailableSize();
  layout_box_->setOverrideContainingBlockContentLogicalWidth(
      available_size.inline_size);
  layout_box_->setOverrideContainingBlockContentLogicalHeight(
      available_size.block_size);
  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(NGPhysicalFragmentBase::kFragmentBox);
  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.ToFragment();
}

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

}  // namespace blink
