// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/layout/block_formatting_context.h"

#include <algorithm>

#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/box.h"

namespace cobalt {
namespace layout {

BlockFormattingContext::BlockFormattingContext(
    const LayoutParams& layout_params)
    : layout_params_(layout_params), collapsing_margin_(0) {}

BlockFormattingContext::~BlockFormattingContext() {}

void BlockFormattingContext::UpdateRect(Box* child_box) {
  DCHECK(!child_box->IsAbsolutelyPositioned());

  child_box->UpdateSize(layout_params_);
  UpdatePosition(child_box);

  // Shrink-to-fit width cannot be less than the width of the widest child.
  //   https://www.w3.org/TR/CSS21/visudet.html#float-width
  set_shrink_to_fit_width(
      std::max(shrink_to_fit_width(),
               child_box->GetMarginBoxRightEdgeOffsetFromContainingBlock()));

  // If "height" is "auto", the used value is the distance from box's top
  // content edge to the bottom edge of the bottom margin of its last in-flow
  // child.
  //   https://www.w3.org/TR/CSS21/visudet.html#normal-block
  set_auto_height(child_box->GetMarginBoxBottomEdgeOffsetFromContainingBlock());
  collapsing_margin_ = child_box->margin_bottom();

  // The baseline of an "inline-block" is the baseline of its last line box
  // in the normal flow, unless it has no in-flow line boxes.
  //   https://www.w3.org/TR/CSS21/visudet.html#line-height
  if (child_box->AffectsBaselineInBlockFormattingContext()) {
    set_baseline_offset_from_top_content_edge(
        child_box->top() + child_box->GetBaselineOffsetFromTopMarginEdge());
  }
}

void BlockFormattingContext::EstimateStaticPosition(Box* child_box) {
  DCHECK(child_box->IsAbsolutelyPositioned());

  // The term "static position" (of an element) refers, roughly, to the position
  // an element would have had in the normal flow.
  //   https://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
  UpdatePosition(child_box);
}

void BlockFormattingContext::UpdatePosition(Box* child_box) {
  DCHECK_EQ(Box::kBlockLevel, child_box->GetLevel());

  // In a block formatting context, each box's left outer edge touches
  // the left edge of the containing block.
  //   https://www.w3.org/TR/CSS21/visuren.html#block-formatting
  child_box->set_left(LayoutUnit());

  // In a block formatting context, boxes are laid out one after the other,
  // vertically, beginning at the top of a containing block. The vertical
  // distance between two sibling boxes is determined by the "margin"
  // properties. Vertical margins between adjacent block-level boxes in a block
  // formatting context collapse.
  //   https://www.w3.org/TR/CSS21/visuren.html#block-formatting

  // When two or more margins collapse, the resulting margin width is the
  // maximum of the collapsing margins' widths.
  //   https://www.w3.org/TR/CSS21/box.html#collapsing-margins
  const LayoutUnit margin_top = child_box->margin_top();
  LayoutUnit collapsed_margin;
  if ((margin_top >= LayoutUnit()) && (collapsing_margin_ >= LayoutUnit())) {
    collapsed_margin = std::max(margin_top, collapsing_margin_);
  } else if ((margin_top < LayoutUnit()) &&
             (collapsing_margin_ < LayoutUnit())) {
    // If there are no positive margins, the maximum of the absolute values of
    // the adjoining margins is deducted from zero.
    collapsed_margin = LayoutUnit() + std::min(margin_top, collapsing_margin_);
  } else {
    // In the case of negative margins, the maximum of the absolute values of
    // the negative adjoining margins is deducted from the maximum of the
    // positive adjoining margins.
    // When there is only one negative and one positive margin, that translates
    // to: The margins are summed.
    DCHECK(collapsing_margin_.GreaterEqualOrNaN(LayoutUnit()) ||
           margin_top.GreaterEqualOrNaN(LayoutUnit()));
    collapsed_margin = collapsing_margin_ + margin_top;
  }

  LayoutUnit combined_margin = collapsing_margin_ + margin_top;
  child_box->set_top(auto_height() - combined_margin + collapsed_margin);
}

}  // namespace layout
}  // namespace cobalt
