// 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_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 "core/layout/ng/ng_box_fragment.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,
                         NGFragment** 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()) {
    NGPhysicalFragment* 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_ = toNGPhysicalBoxFragment(fragment);

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

void NGBlockNode::UpdateLayoutBox(NGPhysicalBoxFragment* 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.
  NGPhysicalFragment* physical_fragment;
  while (!minmax_coordinator->Tick(&physical_fragment))
    continue;
  NGBoxFragment* fragment = new NGBoxFragment(
      FromPlatformWritingMode(Style()->getWritingMode()), Style()->direction(),
      toNGPhysicalBoxFragment(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 NGBoxFragment(
      FromPlatformWritingMode(Style()->getWritingMode()), Style()->direction(),
      toNGPhysicalBoxFragment(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();
  }
}

NGPhysicalBoxFragment* NGBlockNode::RunOldLayout(
    const NGConstraintSpace& constraint_space) {
  NGLogicalSize available_size = constraint_space.PercentageResolutionSize();
  layout_box_->setOverrideContainingBlockContentLogicalWidth(
      available_size.inline_size);
  layout_box_->setOverrideContainingBlockContentLogicalHeight(
      available_size.block_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);
  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_);
  DCHECK(layout_box_->isOutOfFlowPositioned());
  layout_box_->containingBlock()->insertPositionedObject(layout_box_);
}

}  // namespace blink
