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

#include "core/layout/ng/ng_constraint_space.h"
#include "core/layout/ng/ng_length_utils.h"
#include "core/style/ComputedStyle.h"
#include "platform/LengthFunctions.h"

namespace blink {

namespace {

bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) {
  Length width = style.width();
  return width.isIntrinsic() ||
         (width.isAuto() && (style.left().isAuto() || style.right().isAuto()));
}

bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) {
  Length height = style.height();
  return height.isIntrinsic() ||
         (height.isAuto() && (style.top().isAuto() || style.bottom().isAuto()));
}

// Implement absolute horizontal size resolution algorithm.
// https://www.w3.org/TR/css-position-3/#abs-non-replaced-width
void ComputeAbsoluteHorizontal(
    const NGConstraintSpace& space,
    const ComputedStyle& style,
    const NGStaticPosition& static_position,
    const Optional<MinAndMaxContentSizes>& child_minmax,
    NGAbsolutePhysicalPosition* position) {
  NGLogicalSize percentage_logical = space.PercentageResolutionSize();
  NGPhysicalSize percentage_physical =
      percentage_logical.ConvertToPhysical(space.WritingMode());
  LayoutUnit border_left(style.borderLeftWidth());
  LayoutUnit border_right(style.borderRightWidth());
  LayoutUnit padding_left =
      valueForLength(style.paddingLeft(), percentage_logical.inline_size);
  LayoutUnit padding_right =
      valueForLength(style.paddingRight(), percentage_logical.inline_size);
  Optional<LayoutUnit> margin_left;
  if (!style.marginLeft().isAuto())
    margin_left =
        valueForLength(style.marginLeft(), percentage_logical.inline_size);
  Optional<LayoutUnit> margin_right;
  if (!style.marginRight().isAuto())
    margin_right =
        valueForLength(style.marginRight(), percentage_logical.inline_size);
  Optional<LayoutUnit> left;
  if (!style.left().isAuto())
    left = valueForLength(style.left(), percentage_physical.width);
  Optional<LayoutUnit> right;
  if (!style.right().isAuto())
    right = valueForLength(style.right(), percentage_physical.width);
  LayoutUnit border_padding =
      border_left + border_right + padding_left + padding_right;
  Optional<LayoutUnit> width;
  if (!style.width().isAuto()) {
    if (space.WritingMode() == kHorizontalTopBottom) {
      width = ResolveInlineLength(space, style, child_minmax, style.width(),
                                  LengthResolveType::kContentSize);
    } else {
      LayoutUnit computed_width =
          child_minmax.has_value() ? child_minmax->max_content : LayoutUnit();
      width = ResolveBlockLength(space, style, style.width(), computed_width,
                                 LengthResolveType::kContentSize);
    }
  }

  NGPhysicalSize container_size =
      space.AvailableSize().ConvertToPhysical(space.WritingMode());
  DCHECK(container_size.width != NGSizeIndefinite);

  // Solving the equation:
  // left + marginLeft + width + marginRight + right  = container width
  if (!left && !right && !width) {
    // Standard: "If all three of left, width, and right are auto:"
    if (!margin_left)
      margin_left = LayoutUnit();
    if (!margin_right)
      margin_right = LayoutUnit();
    DCHECK(child_minmax.has_value());
    width = child_minmax->ShrinkToFit(container_size.width);
    if (space.Direction() == TextDirection::kLtr) {
      left = static_position.LeftPosition(container_size.width, *width,
                                          *margin_left, *margin_right);
    } else {
      right = static_position.RightPosition(container_size.width, *width,
                                            *margin_left, *margin_right);
    }
  } else if (left && right && width) {
    // Standard: "If left, right, and width are not auto:"
    // Compute margins.
    LayoutUnit margin_space = container_size.width - *left - *right - *width;
    // When both margins are auto.
    if (!margin_left && !margin_right) {
      if (margin_space > 0) {
        margin_left = margin_space / 2;
        margin_right = margin_space / 2;
      } else {
        // Margins are negative.
        if (space.Direction() == TextDirection::kLtr) {
          margin_left = LayoutUnit();
          margin_right = margin_space;
        } else {
          margin_right = LayoutUnit();
          margin_left = margin_space;
        }
      }
    } else if (!margin_left) {
      margin_left = margin_space - *margin_right;
    } else if (!margin_right) {
      margin_right = margin_space - *margin_left;
    } else {
      // Are values overconstrained?
      LayoutUnit margin_extra = margin_space - *margin_left - *margin_right;
      if (margin_extra) {
        // Relax the end.
        if (space.Direction() == TextDirection::kLtr)
          right = *right + margin_extra;
        else
          left = *left + margin_extra;
      }
    }
  }

  // Set unknown margins.
  if (!margin_left)
    margin_left = LayoutUnit();
  if (!margin_right)
    margin_right = LayoutUnit();

  // Rules 1 through 3, 2 out of 3 are unknown.
  if (!left && !width) {
    // Rule 1: left/width are unknown.
    DCHECK(right.has_value());
    DCHECK(child_minmax.has_value());
    width = child_minmax->ShrinkToFit(container_size.width);
  } else if (!left && !right) {
    // Rule 2.
    DCHECK(width.has_value());
    if (space.Direction() == TextDirection::kLtr)
      left = static_position.LeftPosition(container_size.width, *width,
                                          *margin_left, *margin_right);
    else
      right = static_position.RightPosition(container_size.width, *width,
                                            *margin_left, *margin_right);
  } else if (!width && !right) {
    // Rule 3.
    DCHECK(child_minmax.has_value());
    width = child_minmax->ShrinkToFit(container_size.width);
  }

  // Rules 4 through 6, 1 out of 3 are unknown.
  if (!left) {
    left =
        container_size.width - *right - *width - *margin_left - *margin_right;
  } else if (!right) {
    right =
        container_size.width - *left - *width - *margin_left - *margin_right;
  } else if (!width) {
    width =
        container_size.width - *left - *right - *margin_left - *margin_right;
  }
  DCHECK_EQ(container_size.width,
            *left + *right + *margin_left + *margin_right + *width);

  // Negative widths are not allowed.
  width = std::max(*width, border_padding);

  position->inset.left = *left + *margin_left;
  position->inset.right = *right + *margin_right;
  position->size.width = *width;
}

// Implements absolute vertical size resolution algorithm.
// https://www.w3.org/TR/css-position-3/#abs-non-replaced-height
void ComputeAbsoluteVertical(
    const NGConstraintSpace& space,
    const ComputedStyle& style,
    const NGStaticPosition& static_position,
    const Optional<MinAndMaxContentSizes>& child_minmax,
    NGAbsolutePhysicalPosition* position) {
  NGLogicalSize percentage_logical = space.PercentageResolutionSize();
  NGPhysicalSize percentage_physical =
      percentage_logical.ConvertToPhysical(space.WritingMode());

  LayoutUnit border_top(style.borderTopWidth());
  LayoutUnit border_bottom(style.borderBottomWidth());
  LayoutUnit padding_top =
      valueForLength(style.paddingTop(), percentage_logical.inline_size);
  LayoutUnit padding_bottom =
      valueForLength(style.paddingBottom(), percentage_logical.inline_size);
  Optional<LayoutUnit> margin_top;
  if (!style.marginTop().isAuto())
    margin_top =
        valueForLength(style.marginTop(), percentage_logical.inline_size);
  Optional<LayoutUnit> margin_bottom;
  if (!style.marginBottom().isAuto())
    margin_bottom =
        valueForLength(style.marginBottom(), percentage_logical.inline_size);
  Optional<LayoutUnit> top;
  if (!style.top().isAuto())
    top = valueForLength(style.top(), percentage_physical.height);
  Optional<LayoutUnit> bottom;
  if (!style.bottom().isAuto())
    bottom = valueForLength(style.bottom(), percentage_physical.height);
  LayoutUnit border_padding =
      border_top + border_bottom + padding_top + padding_bottom;

  Optional<LayoutUnit> height;
  if (!style.height().isAuto()) {
    if (space.WritingMode() == kHorizontalTopBottom) {
      LayoutUnit computed_height =
          child_minmax.has_value() ? child_minmax->max_content : LayoutUnit();
      height = ResolveBlockLength(space, style, style.height(), computed_height,
                                  LengthResolveType::kContentSize);
    } else {
      height = ResolveInlineLength(space, style, child_minmax, style.height(),
                                   LengthResolveType::kContentSize);
    }
  }

  NGPhysicalSize container_size =
      space.AvailableSize().ConvertToPhysical(space.WritingMode());
  DCHECK(container_size.height != NGSizeIndefinite);

  // Solving the equation:
  // top + marginTop + height + marginBottom + bottom
  // + border_padding = container height
  if (!top && !bottom && !height) {
    // Standard: "If all three of top, height, and bottom are auto:"
    if (!margin_top)
      margin_top = LayoutUnit();
    if (!margin_bottom)
      margin_bottom = LayoutUnit();
    DCHECK(child_minmax.has_value());
    height = child_minmax->ShrinkToFit(container_size.height);
    top = static_position.TopPosition(container_size.height, *height,
                                      *margin_top, *margin_bottom);
  } else if (top && bottom && height) {
    // Standard: "If top, bottom, and height are not auto:"
    // Compute margins.
    LayoutUnit margin_space = container_size.height - *top - *bottom - *height;
    // When both margins are auto.
    if (!margin_top && !margin_bottom) {
      if (margin_space > 0) {
        margin_top = margin_space / 2;
        margin_bottom = margin_space / 2;
      } else {
        // Margin space is over-constrained.
        margin_top = LayoutUnit();
        margin_bottom = margin_space;
      }
    } else if (!margin_top) {
      margin_top = margin_space - *margin_bottom;
    } else if (!margin_bottom) {
      margin_bottom = margin_space - *margin_top;
    } else {
      LayoutUnit margin_extra = margin_space - *margin_top - *margin_bottom;
      if (margin_extra)
        bottom = *bottom + margin_extra;
    }
  }

  // Set unknown margins.
  if (!margin_top)
    margin_top = LayoutUnit();
  if (!margin_bottom)
    margin_bottom = LayoutUnit();

  // Rules 1 through 3, 2 out of 3 are unknown, fix 1.
  if (!top && !height) {
    // Rule 1.
    DCHECK(bottom.has_value());
    DCHECK(child_minmax.has_value());
    height = child_minmax->ShrinkToFit(container_size.height);
  } else if (!top && !bottom) {
    // Rule 2.
    DCHECK(height.has_value());
    top = static_position.TopPosition(container_size.height, *height,
                                      *margin_top, *margin_bottom);
  } else if (!height && !bottom) {
    // Rule 3.
    DCHECK(child_minmax.has_value());
    height = child_minmax->ShrinkToFit(container_size.height);
  }

  // Rules 4 through 6, 1 out of 3 are unknown.
  if (!top) {
    top = container_size.height - *bottom - *height - *margin_top -
          *margin_bottom;
  } else if (!bottom) {
    bottom =
        container_size.height - *top - *height - *margin_top - *margin_bottom;
  } else if (!height) {
    height =
        container_size.height - *top - *bottom - *margin_top - *margin_bottom;
  }
  DCHECK_EQ(container_size.height,
            *top + *bottom + *margin_top + *margin_bottom + *height);

  // Negative heights are not allowed.
  height = std::max(*height, border_padding);

  position->inset.top = *top + *margin_top;
  position->inset.bottom = *bottom + *margin_bottom;
  position->size.height = *height;
}

}  // namespace

String NGAbsolutePhysicalPosition::ToString() const {
  return String::format("INSET(LRTB):%d,%d,%d,%d SIZE:%dx%d",
                        inset.left.toInt(), inset.right.toInt(),
                        inset.top.toInt(), inset.bottom.toInt(),
                        size.width.toInt(), size.height.toInt());
}

bool AbsoluteNeedsChildBlockSize(const ComputedStyle& style) {
  if (style.isHorizontalWritingMode())
    return AbsoluteVerticalNeedsEstimate(style);
  else
    return AbsoluteHorizontalNeedsEstimate(style);
}

bool AbsoluteNeedsChildInlineSize(const ComputedStyle& style) {
  if (style.isHorizontalWritingMode())
    return AbsoluteHorizontalNeedsEstimate(style);
  else
    return AbsoluteVerticalNeedsEstimate(style);
}

bool IsContainingBlockForAbsoluteChild(const ComputedStyle& container_style,
                                       const ComputedStyle& child_style) {
  EPosition position = child_style.position();
  bool contains_fixed = container_style.canContainFixedPositionObjects();
  bool contains_absolute =
      container_style.canContainAbsolutePositionObjects() || contains_fixed;

  return (contains_absolute && position == AbsolutePosition) ||
         (contains_fixed && position == FixedPosition);
}

NGAbsolutePhysicalPosition ComputePartialAbsoluteWithChildInlineSize(
    const NGConstraintSpace& space,
    const ComputedStyle& style,
    const NGStaticPosition& static_position,
    const Optional<MinAndMaxContentSizes>& child_minmax) {
  NGAbsolutePhysicalPosition position;
  if (style.isHorizontalWritingMode())
    ComputeAbsoluteHorizontal(space, style, static_position, child_minmax,
                              &position);
  else {
    ComputeAbsoluteVertical(space, style, static_position, child_minmax,
                            &position);
  }
  return position;
}

void ComputeFullAbsoluteWithChildBlockSize(
    const NGConstraintSpace& space,
    const ComputedStyle& style,
    const NGStaticPosition& static_position,
    const Optional<LayoutUnit>& child_block_size,
    NGAbsolutePhysicalPosition* position) {
  // After partial size has been computed, child block size is either
  // unknown, or fully computed, there is no minmax.
  // To express this, a 'fixed' minmax is created where
  // min and max are the same.
  Optional<MinAndMaxContentSizes> child_minmax;
  if (child_block_size.has_value()) {
    child_minmax = MinAndMaxContentSizes{*child_block_size, *child_block_size};
  }
  if (style.isHorizontalWritingMode())
    ComputeAbsoluteVertical(space, style, static_position, child_minmax,
                            position);
  else {
    ComputeAbsoluteHorizontal(space, style, static_position, child_minmax,
                              position);
  }
}

}  // namespace blink
