// Copyright 2015 The Cobalt Authors. 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 <memory>

#include "cobalt/layout/block_container_box.h"

#include "cobalt/layout/formatting_context.h"
#include "cobalt/layout/used_style.h"

namespace cobalt {
namespace layout {

BlockContainerBox::BlockContainerBox(
    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
        css_computed_style_declaration,
    BaseDirection base_direction, UsedStyleProvider* used_style_provider,
    LayoutStatTracker* layout_stat_tracker)
    : ContainerBox(css_computed_style_declaration, used_style_provider,
                   layout_stat_tracker),
      base_direction_(base_direction) {}

BlockContainerBox::~BlockContainerBox() {}

// Updates used values of "width" and "margin" properties based on
// https://www.w3.org/TR/CSS21/visudet.html#Computing_widths_and_margins.
void BlockContainerBox::UpdateContentWidthAndMargins(
    BaseDirection containing_block_direction,
    LayoutUnit containing_block_width, bool shrink_to_fit_width_forced,
    bool width_depends_on_containing_block,
    const base::Optional<LayoutUnit>& maybe_left,
    const base::Optional<LayoutUnit>& maybe_right,
    const base::Optional<LayoutUnit>& maybe_margin_left,
    const base::Optional<LayoutUnit>& maybe_margin_right,
    const base::Optional<LayoutUnit>& maybe_width,
    const base::Optional<LayoutUnit>& maybe_height) {
  if (IsAbsolutelyPositioned()) {
    UpdateWidthAssumingAbsolutelyPositionedBox(
        containing_block_direction, containing_block_width,
        maybe_left, maybe_right, maybe_width,
        maybe_margin_left, maybe_margin_right, maybe_height);
  } else {
    base::Optional<LayoutUnit> maybe_nulled_width = maybe_width;
    Level forced_level = GetLevel();
    if (shrink_to_fit_width_forced) {
      forced_level = kInlineLevel;
      // Break circular dependency if needed.
      if (width_depends_on_containing_block) {
        maybe_nulled_width = base::nullopt;
      }
    }

    switch (forced_level) {
      case kBlockLevel:
        UpdateWidthAssumingBlockLevelInFlowBox(
            containing_block_direction, containing_block_width,
            maybe_nulled_width, maybe_margin_left, maybe_margin_right);
        break;
      case kInlineLevel:
        UpdateWidthAssumingInlineLevelInFlowBox(
            containing_block_width, maybe_nulled_width, maybe_margin_left,
            maybe_margin_right, maybe_height);
        break;
    }
  }
}

// Updates used values of "height" and "margin" properties based on
// https://www.w3.org/TR/CSS21/visudet.html#Computing_heights_and_margins.
void BlockContainerBox::UpdateContentHeightAndMargins(
    const SizeLayoutUnit& containing_block_size,
    const base::Optional<LayoutUnit>& maybe_top,
    const base::Optional<LayoutUnit>& maybe_bottom,
    const base::Optional<LayoutUnit>& maybe_margin_top,
    const base::Optional<LayoutUnit>& maybe_margin_bottom,
    const base::Optional<LayoutUnit>& maybe_height) {
  LayoutParams child_layout_params;
  LayoutParams absolute_child_layout_params;
  child_layout_params.containing_block_direction = base_direction_;
  absolute_child_layout_params.containing_block_direction = base_direction_;
  if (AsAnonymousBlockBox()) {
    // Anonymous block boxes are ignored when resolving percentage values
    // that would refer to it: the closest non-anonymous ancestor box is used
    // instead.
    //   https://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level
    child_layout_params.containing_block_size = containing_block_size;
  } else {
    // If the element's position is "relative" or "static", the containing block
    // is formed by the content edge of the nearest block container ancestor
    // box.
    //   https://www.w3.org/TR/CSS21/visudet.html#containing-block-details
    child_layout_params.containing_block_size.set_width(width());
    // If the element has 'position: absolute', ...
    // the containing block is formed by the padding edge of the ancestor.
    //   http://www.w3.org/TR/CSS21/visudet.html#containing-block-details
    absolute_child_layout_params.containing_block_size.set_width(
        GetPaddingBoxWidth());
    // The "auto" height is not known yet but it shouldn't matter for in-flow
    // children, as per:
    //
    // If the height of the containing block is not specified explicitly (i.e.,
    // it depends on content height), and this element is not absolutely
    // positioned, the value [of "height"] computes to "auto".
    //   https://www.w3.org/TR/CSS21/visudet.html#the-height-property
    if (maybe_height) {
      child_layout_params.containing_block_size.set_height(*maybe_height);
    } else if (maybe_top && maybe_bottom) {
      child_layout_params.containing_block_size.set_height(
          containing_block_size.height() - *maybe_top - *maybe_bottom);
    } else {
      child_layout_params.containing_block_size.set_height(LayoutUnit());
    }
  }
  child_layout_params.maybe_margin_top = maybe_margin_top;
  child_layout_params.maybe_margin_bottom = maybe_margin_bottom;
  child_layout_params.maybe_height = maybe_height;

  std::unique_ptr<FormattingContext> formatting_context =
      UpdateRectOfInFlowChildBoxes(child_layout_params);

  if (IsAbsolutelyPositioned()) {
    UpdateHeightAssumingAbsolutelyPositionedBox(
        containing_block_size.height(), maybe_top, maybe_bottom, maybe_height,
        maybe_margin_top, maybe_margin_bottom, *formatting_context);
  } else {
    UpdateHeightAssumingInFlowBox(maybe_height, maybe_margin_top,
                                  maybe_margin_bottom, *formatting_context);
  }

  // Positioned children are laid out at the end as their position and size
  // depends on the size of the containing block as well as possibly their
  // previously calculated in-flow position.
  child_layout_params.containing_block_size.set_height(height());
  absolute_child_layout_params.containing_block_size.set_height(
      GetPaddingBoxHeight());
  UpdateRectOfPositionedChildBoxes(child_layout_params,
                                   absolute_child_layout_params);

  if (formatting_context->maybe_baseline_offset_from_top_content_edge()) {
    maybe_baseline_offset_from_top_margin_edge_ =
        margin_top() + border_top_width() + padding_top() +
        *formatting_context->maybe_baseline_offset_from_top_content_edge();
  } else {
    maybe_baseline_offset_from_top_margin_edge_ = base::nullopt;
  }
}

void BlockContainerBox::UpdateContentSizeAndMargins(
    const LayoutParams& layout_params) {
  base::Optional<LayoutUnit> maybe_height = GetUsedHeightIfNotAuto(
      computed_style(), layout_params.containing_block_size, NULL);
  bool width_depends_on_containing_block;

  base::Optional<LayoutUnit> maybe_top = GetUsedTopIfNotAuto(
      computed_style(), layout_params.containing_block_size);
  base::Optional<LayoutUnit> maybe_bottom = GetUsedBottomIfNotAuto(
      computed_style(), layout_params.containing_block_size);
  base::Optional<LayoutUnit> maybe_margin_top = GetUsedMarginTopIfNotAuto(
      computed_style(), layout_params.containing_block_size);
  base::Optional<LayoutUnit> maybe_margin_bottom = GetUsedMarginBottomIfNotAuto(
      computed_style(), layout_params.containing_block_size);

  if (layout_params.freeze_height) {
    maybe_height = height();
  }

  if (!layout_params.freeze_width) {
    base::Optional<LayoutUnit> maybe_width = GetUsedWidthIfNotAuto(
        computed_style(), layout_params.containing_block_size,
        &width_depends_on_containing_block);
    base::Optional<LayoutUnit> maybe_margin_left = GetUsedMarginLeftIfNotAuto(
        computed_style(), layout_params.containing_block_size);
    base::Optional<LayoutUnit> maybe_margin_right = GetUsedMarginRightIfNotAuto(
        computed_style(), layout_params.containing_block_size);
    base::Optional<LayoutUnit> maybe_left = GetUsedLeftIfNotAuto(
        computed_style(), layout_params.containing_block_size);
    base::Optional<LayoutUnit> maybe_right = GetUsedRightIfNotAuto(
        computed_style(), layout_params.containing_block_size);

    UpdateContentWidthAndMargins(layout_params.containing_block_direction,
                                 layout_params.containing_block_size.width(),
                                 layout_params.shrink_to_fit_width_forced,
                                 width_depends_on_containing_block, maybe_left,
                                 maybe_right, maybe_margin_left,
                                 maybe_margin_right, maybe_width, maybe_height);

    // If the tentative used width is greater than 'max-width', the rules above
    // are applied again, but this time using the computed value of 'max-width'
    // as the computed value for 'width'.
    //   https://www.w3.org/TR/CSS21/visudet.html#min-max-widths
    bool max_width_depends_on_containing_block;
    base::Optional<LayoutUnit> maybe_max_width = GetUsedMaxWidthIfNotNone(
        computed_style(), layout_params.containing_block_size,
        &max_width_depends_on_containing_block);
    if (maybe_max_width && width() > maybe_max_width.value()) {
      UpdateContentWidthAndMargins(
          layout_params.containing_block_direction,
          layout_params.containing_block_size.width(),
          layout_params.shrink_to_fit_width_forced,
          max_width_depends_on_containing_block, maybe_left, maybe_right,
          maybe_margin_left, maybe_margin_right, maybe_max_width, maybe_height);
    }

    // If the resulting width is smaller than 'min-width', the rules above are
    // applied again, but this time using the value of 'min-width' as the
    // computed value for 'width'.
    //   https://www.w3.org/TR/CSS21/visudet.html#min-max-widths
    bool min_width_depends_on_containing_block;
    base::Optional<LayoutUnit> maybe_min_width = GetUsedMinWidthIfNotAuto(
        computed_style(), layout_params.containing_block_size,
        &min_width_depends_on_containing_block);
    if (maybe_min_width && (width() < maybe_min_width.value_or(LayoutUnit()))) {
      UpdateContentWidthAndMargins(
          layout_params.containing_block_direction,
          layout_params.containing_block_size.width(),
          layout_params.shrink_to_fit_width_forced,
          min_width_depends_on_containing_block, maybe_left, maybe_right,
          maybe_margin_left, maybe_margin_right, maybe_min_width, maybe_height);
    }
  }

  UpdateContentHeightAndMargins(layout_params.containing_block_size, maybe_top,
                                maybe_bottom, maybe_margin_top,
                                maybe_margin_bottom, maybe_height);

  // If the tentative height is greater than 'max-height', the rules above are
  // applied again, but this time using the value of 'max-height' as the
  // computed value for 'height'.
  //   https://www.w3.org/TR/CSS21/visudet.html#min-max-heights
  base::Optional<LayoutUnit> maybe_max_height = GetUsedMaxHeightIfNotNone(
      computed_style(), layout_params.containing_block_size);
  if (maybe_max_height && height() > maybe_max_height.value()) {
    UpdateContentHeightAndMargins(layout_params.containing_block_size,
                                  maybe_top, maybe_bottom, maybe_margin_top,
                                  maybe_margin_bottom, maybe_max_height);
  }

  // If the resulting height is smaller than 'min-height', the rules above are
  // applied again, but this time using the value of 'min-height' as the
  // computed value for 'height'.
  //   https://www.w3.org/TR/CSS21/visudet.html#min-max-heights
  base::Optional<LayoutUnit> min_height = GetUsedMinHeightIfNotAuto(
      computed_style(), layout_params.containing_block_size);
  if (min_height && (height() < min_height.value())) {
    UpdateContentHeightAndMargins(layout_params.containing_block_size,
                                  maybe_top, maybe_bottom, maybe_margin_top,
                                  maybe_margin_bottom, min_height);
  }
}

WrapResult BlockContainerBox::TryWrapAt(
    WrapAtPolicy /*wrap_at_policy*/,
    WrapOpportunityPolicy /*wrap_opportunity_policy*/,
    bool /*is_line_existence_justified*/, LayoutUnit /*available_width*/,
    bool /*should_collapse_trailing_white_space*/) {
  DCHECK(!IsAbsolutelyPositioned());
  DCHECK_EQ(kInlineLevel, GetLevel());
  return kWrapResultNoWrap;
}

bool BlockContainerBox::TrySplitAtSecondBidiLevelRun() { return false; }

base::Optional<int> BlockContainerBox::GetBidiLevel() const {
  return base::Optional<int>();
}

void BlockContainerBox::SetShouldCollapseLeadingWhiteSpace(
    bool /*should_collapse_leading_white_space*/) {
  DCHECK_EQ(kInlineLevel, GetLevel());
  // Do nothing.
}

void BlockContainerBox::SetShouldCollapseTrailingWhiteSpace(
    bool /*should_collapse_trailing_white_space*/) {
  DCHECK_EQ(kInlineLevel, GetLevel());
  // Do nothing.
}

bool BlockContainerBox::HasLeadingWhiteSpace() const {
  DCHECK_EQ(kInlineLevel, GetLevel());
  return false;
}

bool BlockContainerBox::HasTrailingWhiteSpace() const {
  DCHECK_EQ(kInlineLevel, GetLevel());
  return false;
}

bool BlockContainerBox::IsCollapsed() const {
  DCHECK_EQ(kInlineLevel, GetLevel());
  return false;
}

bool BlockContainerBox::JustifiesLineExistence() const {
  DCHECK_EQ(kInlineLevel, GetLevel());
  return true;
}

bool BlockContainerBox::AffectsBaselineInBlockFormattingContext() const {
  return static_cast<bool>(maybe_baseline_offset_from_top_margin_edge_);
}

LayoutUnit BlockContainerBox::GetBaselineOffsetFromTopMarginEdge() const {
  return maybe_baseline_offset_from_top_margin_edge_.value_or(
      GetMarginBoxHeight());
}

BlockContainerBox* BlockContainerBox::AsBlockContainerBox() { return this; }
const BlockContainerBox* BlockContainerBox::AsBlockContainerBox() const {
  return this;
}

scoped_refptr<ContainerBox> BlockContainerBox::TrySplitAtEnd() {
  return scoped_refptr<ContainerBox>();
}

bool BlockContainerBox::IsTransformable() const { return true; }

#ifdef COBALT_BOX_DUMP_ENABLED

void BlockContainerBox::DumpProperties(std::ostream* stream) const {
  ContainerBox::DumpProperties(stream);

  *stream << std::boolalpha << "affects_baseline_in_block_formatting_context="
          << AffectsBaselineInBlockFormattingContext() << " "
          << std::noboolalpha;
}

#endif  // COBALT_BOX_DUMP_ENABLED

// Based on https://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width.
//
// The constraint that determines the used values for these elements is:
//       "left" + "margin-left" + "border-left-width" + "padding-left"
//     + "width"
//     + "padding-right" + "border-right-width" + "margin-right" + "right"
//     = width of containing block
void BlockContainerBox::UpdateWidthAssumingAbsolutelyPositionedBox(
    BaseDirection containing_block_direction,
    LayoutUnit containing_block_width,
    const base::Optional<LayoutUnit>& maybe_left,
    const base::Optional<LayoutUnit>& maybe_right,
    const base::Optional<LayoutUnit>& maybe_width,
    const base::Optional<LayoutUnit>& maybe_margin_left,
    const base::Optional<LayoutUnit>& maybe_margin_right,
    const base::Optional<LayoutUnit>& maybe_height) {
  // If all three of "left", "width", and "right" are "auto":
  if (!maybe_left && !maybe_width && !maybe_right) {
    // First set any "auto" values for "margin-left" and "margin-right" to 0.
    set_margin_left(maybe_margin_left.value_or(LayoutUnit()));
    set_margin_right(maybe_margin_right.value_or(LayoutUnit()));

    // Then, if the "direction" property of the element establishing the
    // static-position containing block is "ltr"...
    if (containing_block_direction == kLeftToRightBaseDirection) {
      // ...set "left" to the static position...
      set_left(GetStaticPositionLeft());

      // ...and apply rule number three (the width is shrink-to-fit; solve for
      // "right").
      set_width(GetShrinkToFitWidth(containing_block_width, maybe_height));
    } else {
      // ...otherwise, set "right" to the static position...
      // ...and apply rule number one (the width is shrink-to-fit; solve for
      // "left").
      set_width(GetShrinkToFitWidth(containing_block_width, maybe_height));
      set_left(containing_block_width - GetStaticPositionRight() -
               GetMarginBoxWidth());
    }
    return;
  }

  // If none of the three is "auto":
  if (maybe_left && maybe_width && maybe_right) {
    set_left(*maybe_left);
    set_width(*maybe_width);

    LayoutUnit horizontal_margin_sum = containing_block_width - *maybe_left -
                                       GetBorderBoxWidth() - *maybe_right;

    if (!maybe_margin_left && !maybe_margin_right) {
      // If both "margin-left" and "margin-right" are "auto", solve the equation
      // under the extra constraint that the two margins get equal values...
      LayoutUnit horizontal_margin = horizontal_margin_sum / 2;
      if (horizontal_margin < LayoutUnit()) {
        // ...unless this would make them negative, in which case when direction
        // of the containing block is "ltr" ("rtl"), set "margin-left"
        // ("margin-right") to zero and solve for "margin-right"
        // ("margin-left").
        if (containing_block_direction == kLeftToRightBaseDirection) {
          set_margin_left(LayoutUnit());
          set_margin_right(horizontal_margin_sum);
        } else {
          set_margin_left(horizontal_margin_sum);
          set_margin_right(LayoutUnit());
        }
      } else {
        set_margin_left(horizontal_margin);
        set_margin_right(horizontal_margin);
      }
    } else if (!maybe_margin_left) {
      // If one of "margin-left" or "margin-right" is "auto", solve the equation
      // for that value.
      set_margin_left(horizontal_margin_sum - *maybe_margin_right);
      set_margin_right(*maybe_margin_right);
    } else if (!maybe_margin_right) {
      // If one of "margin-left" or "margin-right" is "auto", solve the equation
      // for that value.
      set_margin_left(*maybe_margin_left);
      set_margin_right(horizontal_margin_sum - *maybe_margin_left);
    } else {
      // If the values are over-constrained, ignore the value for "left" (in
      // case the "direction" property of the containing block is "rtl") or
      // "right" (in case "direction" is "ltr") and solve for that value.
      set_margin_left(*maybe_margin_left);
      set_margin_right(*maybe_margin_right);
      if (containing_block_direction == kRightToLeftBaseDirection) {
        set_left(containing_block_width - GetMarginBoxWidth() - *maybe_right);
      }
    }
    return;
  }

  // Otherwise, set "auto" values for "margin-left" and "margin-right" to 0...
  set_margin_left(maybe_margin_left.value_or(LayoutUnit()));
  set_margin_right(maybe_margin_right.value_or(LayoutUnit()));

  // ...and pick the one of the following six rules that applies.

  // 1. "left" and "width" are "auto" and "right" is not "auto"...
  if (!maybe_left && !maybe_width && maybe_right) {
    // ...then the width is shrink-to-fit.
    set_width(GetShrinkToFitWidth(containing_block_width, maybe_height));
    // Then solve for "left".
    set_left(containing_block_width - GetMarginBoxWidth() - *maybe_right);
    return;
  }

  // 2. "left" and "right" are "auto" and "width" is not "auto"...
  if (!maybe_left && !maybe_right && maybe_width) {
    set_width(*maybe_width);
    // ...if the "direction" property of the element establishing the
    // static-position containing block is "ltr" set "left" to the static
    // position, otherwise set "right" to the static position. Then solve for
    // "left" (if "direction" is "rtl") or "right" (if "direction" is "ltr").
    if (containing_block_direction == kLeftToRightBaseDirection) {
      set_left(GetStaticPositionLeft());
    } else {
      set_left(containing_block_width - GetStaticPositionRight() -
               GetMarginBoxWidth());
    }
    DCHECK_EQ(left(), left());  // Check for NaN.
    return;
  }

  // 3. "width" and "right" are "auto" and "left" is not "auto"...
  if (!maybe_width && !maybe_right && maybe_left) {
    set_left(*maybe_left);
    // ...then the width is shrink-to-fit.
    set_width(GetShrinkToFitWidth(containing_block_width, maybe_height));
    return;
  }

  // 4. "left" is "auto", "width" and "right" are not "auto"...
  if (!maybe_left && maybe_width && maybe_right) {
    set_width(*maybe_width);
    // ...then solve for "left".
    set_left(containing_block_width - GetMarginBoxWidth() - *maybe_right);
    return;
  }

  // 5. "width" is "auto", "left" and "right" are not "auto"...
  if (!maybe_width && maybe_left && maybe_right) {
    set_left(*maybe_left);
    // ...then solve for "width".
    set_width(containing_block_width - *maybe_left - margin_left() -
              border_left_width() - padding_left() - padding_right() -
              border_right_width() - margin_right() - *maybe_right);
    return;
  }

  // 6. "right" is "auto", "left" and "width" are not "auto".
  if (!maybe_right && maybe_left && maybe_width) {
    set_left(*maybe_left);
    set_width(*maybe_width);
    return;
  }
}

// Based on https://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-height.
//
// The constraint that determines the used values for these elements is:
//       "top" + "margin-top" + "border-top-width" + "padding-top"
//     + "height"
//     + "padding-bottom" + "border-bottom-width" + "margin-bottom" + "bottom"
//     = height of containing block
void BlockContainerBox::UpdateHeightAssumingAbsolutelyPositionedBox(
    LayoutUnit containing_block_height,
    const base::Optional<LayoutUnit>& maybe_top,
    const base::Optional<LayoutUnit>& maybe_bottom,
    const base::Optional<LayoutUnit>& maybe_height,
    const base::Optional<LayoutUnit>& maybe_margin_top,
    const base::Optional<LayoutUnit>& maybe_margin_bottom,
    const FormattingContext& formatting_context) {
  // If all three of "top", "height", and "bottom" are "auto":
  if (!maybe_top && !maybe_height && !maybe_bottom) {
    // First set any "auto" values for "margin-top" and "margin-bottom" to 0.
    set_margin_top(maybe_margin_top.value_or(LayoutUnit()));
    set_margin_bottom(maybe_margin_bottom.value_or(LayoutUnit()));

    // Then set "top" to the static position...
    set_top(GetStaticPositionTop());
    DCHECK_EQ(top(), top());  // Check for NaN.

    // ...and apply rule number three (the height is based on the content).
    set_height(formatting_context.auto_height());
    return;
  }

  // If none of the three is "auto":
  if (maybe_top && maybe_height && maybe_bottom) {
    set_top(*maybe_top);
    set_height(*maybe_height);

    LayoutUnit vertical_margin_sum = containing_block_height - *maybe_top -
                                     GetBorderBoxHeight() - *maybe_bottom;

    if (!maybe_margin_top && !maybe_margin_bottom) {
      // If both "margin-top" and "margin-bottom" are "auto", solve the equation
      // under the extra constraint that the two margins get equal values...
      LayoutUnit vertical_margin = vertical_margin_sum / 2;
      set_margin_top(vertical_margin);
      set_margin_bottom(vertical_margin);
    } else if (!maybe_margin_top) {
      // If one of "margin-top" or "margin-bottom" is "auto", solve the equation
      // for that value.
      set_margin_top(vertical_margin_sum - *maybe_margin_bottom);
      set_margin_bottom(*maybe_margin_bottom);
    } else if (!maybe_margin_bottom) {
      // If one of "margin-top" or "margin-bottom" is "auto", solve the equation
      // for that value.
      set_margin_top(*maybe_margin_top);
      set_margin_bottom(vertical_margin_sum - *maybe_margin_top);
    } else {
      // If the values are over-constrained, ignore the value for "bottom".
      set_margin_top(*maybe_margin_top);
      set_margin_bottom(*maybe_margin_bottom);
    }
    return;
  }

  // Otherwise, set "auto" values for "margin-top" and "margin-bottom" to 0...
  set_margin_top(maybe_margin_top.value_or(LayoutUnit()));
  set_margin_bottom(maybe_margin_bottom.value_or(LayoutUnit()));

  // ...and pick the one of the following six rules that applies.

  // 1. "top" and "height" are "auto" and "bottom" is not "auto"...
  if (!maybe_top && !maybe_height && maybe_bottom) {
    // ...then the height is based on the content.
    set_height(formatting_context.auto_height());
    // Then solve for "top".
    set_top(containing_block_height - GetMarginBoxHeight() - *maybe_bottom);
    return;
  }

  // 2. "top" and "bottom" are "auto" and "height" is not "auto"...
  if (!maybe_top && !maybe_bottom && maybe_height) {
    set_height(*maybe_height);
    // ...then set "top" to the static position.
    set_top(GetStaticPositionTop());
    DCHECK_EQ(top(), top());  // Check for NaN.
    return;
  }

  // 3. "height" and "bottom" are "auto" and "top" is not "auto"...
  if (!maybe_height && !maybe_bottom && maybe_top) {
    set_top(*maybe_top);
    // ...then the height is based on the content.
    set_height(formatting_context.auto_height());
    return;
  }

  // 4. "top" is "auto", "height" and "bottom" are not "auto"...
  if (!maybe_top && maybe_height && maybe_bottom) {
    set_height(*maybe_height);
    // ...then solve for "top".
    set_top(containing_block_height - GetMarginBoxHeight() - *maybe_bottom);
    return;
  }

  // 5. "height" is "auto", "top" and "bottom" are not "auto"...
  if (!maybe_height && maybe_top && maybe_bottom) {
    set_top(*maybe_top);
    // ...then solve for "height".
    set_height(containing_block_height - *maybe_top - margin_top() -
               border_top_width() - padding_top() - padding_bottom() -
               border_bottom_width() - margin_bottom() - *maybe_bottom);
    return;
  }

  // 6. "bottom" is "auto", "top" and "height" are not "auto".
  if (!maybe_bottom && maybe_top && maybe_height) {
    set_top(*maybe_top);
    set_height(*maybe_height);
    return;
  }
}

// Based on https://www.w3.org/TR/CSS21/visudet.html#blockwidth.
//
// The following constraints must hold among the used values of the other
// properties:
//       "margin-left" + "border-left-width" + "padding-left"
//     + "width"
//     + "padding-right" + "border-right-width" + "margin-right"
//     = width of containing block
void BlockContainerBox::UpdateWidthAssumingBlockLevelInFlowBox(
    BaseDirection containing_block_direction,
    LayoutUnit containing_block_width,
    const base::Optional<LayoutUnit>& maybe_width,
    const base::Optional<LayoutUnit>& possibly_overconstrained_margin_left,
    const base::Optional<LayoutUnit>& possibly_overconstrained_margin_right) {
  base::Optional<LayoutUnit> maybe_margin_left =
      possibly_overconstrained_margin_left;
  base::Optional<LayoutUnit> maybe_margin_right =
      possibly_overconstrained_margin_right;

  if (maybe_width) {
    set_width(*maybe_width);
    UpdateHorizontalMarginsAssumingBlockLevelInFlowBox(
        containing_block_direction, containing_block_width, GetBorderBoxWidth(),
        maybe_margin_left, maybe_margin_right);
  } else {
    // If "width" is set to "auto", any other "auto" values become "0" and
    // "width" follows from the resulting equality.
    set_margin_left(maybe_margin_left.value_or(LayoutUnit()));
    set_margin_right(maybe_margin_right.value_or(LayoutUnit()));

    set_width(containing_block_width - margin_left() - border_left_width() -
              padding_left() - padding_right() - border_right_width() -
              margin_right());
  }
}

void BlockContainerBox::UpdateWidthAssumingInlineLevelInFlowBox(
    LayoutUnit containing_block_width,
    const base::Optional<LayoutUnit>& maybe_width,
    const base::Optional<LayoutUnit>& maybe_margin_left,
    const base::Optional<LayoutUnit>& maybe_margin_right,
    const base::Optional<LayoutUnit>& maybe_height) {
  // A computed value of "auto" for "margin-left" or "margin-right" becomes
  // a used value of "0".
  //   https://www.w3.org/TR/CSS21/visudet.html#inlineblock-width
  set_margin_left(maybe_margin_left.value_or(LayoutUnit()));
  set_margin_right(maybe_margin_right.value_or(LayoutUnit()));

  if (!maybe_width) {
    // If "width" is "auto", the used value is the shrink-to-fit width.
    //   https://www.w3.org/TR/CSS21/visudet.html#inlineblock-width
    set_width(GetShrinkToFitWidth(containing_block_width, maybe_height));
  } else {
    set_width(*maybe_width);
  }
}

LayoutUnit BlockContainerBox::GetShrinkToFitWidth(
    LayoutUnit containing_block_width,
    const base::Optional<LayoutUnit>& maybe_height) {
  LayoutParams child_layout_params;
  child_layout_params.containing_block_direction = base_direction_;
  // The available width is the width of the containing block minus
  // the used values of "margin-left", "border-left-width", "padding-left",
  // "padding-right", "border-right-width", "margin-right".
  //   https://www.w3.org/TR/CSS21/visudet.html#shrink-to-fit-float
  child_layout_params.containing_block_size.set_width(
      containing_block_width - margin_left() - border_left_width() -
      padding_left() - padding_right() - border_right_width() - margin_right());
  // The "auto" height is not known yet but it shouldn't matter for in-flow
  // children, as per:
  //
  // If the height of the containing block is not specified explicitly (i.e.,
  // it depends on content height), and this element is not absolutely
  // positioned, the value [of "height"] computes to "auto".
  //   https://www.w3.org/TR/CSS21/visudet.html#the-height-property
  child_layout_params.containing_block_size.set_height(
      maybe_height.value_or(LayoutUnit()));
  // Although the spec does not mention it explicitly, Chromium operates under
  // the assumption that child block-level boxes must shrink instead of
  // expanding when calculating shrink-to-fit width of the parent box.
  child_layout_params.shrink_to_fit_width_forced = true;

  // Do a preliminary layout using the available width as a containing block
  // width. See |InlineFormattingContext::EndUpdates()| for details.
  //
  // TODO: Laying out the children twice has an exponential worst-case
  //       complexity (because every child could lay out itself twice as
  //       well). Figure out if there is a better way.
  std::unique_ptr<FormattingContext> formatting_context =
      UpdateRectOfInFlowChildBoxes(child_layout_params);

  return formatting_context->shrink_to_fit_width();
}

// Based on https://www.w3.org/TR/CSS21/visudet.html#normal-block.
//
// TODO: Implement https://www.w3.org/TR/CSS21/visudet.html#block-root-margin
// when the margin collapsing is supported.
void BlockContainerBox::UpdateHeightAssumingInFlowBox(
    const base::Optional<LayoutUnit>& maybe_height,
    const base::Optional<LayoutUnit>& maybe_margin_top,
    const base::Optional<LayoutUnit>& maybe_margin_bottom,
    const FormattingContext& formatting_context) {
  if (collapsed_empty_margin_) {
    // If empty box has a collapsed margin, only set top margin.
    //   https://www.w3.org/TR/CSS22/box.html#collapsing-margins
    set_margin_top(collapsed_empty_margin_.value());
    set_margin_bottom(LayoutUnit());
  } else {
    // If "margin-top", or "margin-bottom" are "auto", their used value is 0.
    LayoutUnit margin_top =
        collapsed_margin_top_.value_or(maybe_margin_top.value_or(LayoutUnit()));
    LayoutUnit margin_bottom = collapsed_margin_bottom_.value_or(
        maybe_margin_bottom.value_or(LayoutUnit()));
    set_margin_top(margin_top);
    set_margin_bottom(margin_bottom);
  }

  // If "height" is "auto", the used value is the distance from box's top
  // content edge to the first applicable of the following:
  //     1. the bottom edge of the last line box, if the box establishes
  //        an inline formatting context with one or more lines;
  //     2. the bottom edge of the bottom margin of its last in-flow child.
  set_height(maybe_height.value_or(formatting_context.auto_height()));
}

}  // namespace layout
}  // namespace cobalt
