// Copyright 2019 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 "cobalt/layout/flex_container_box.h"

#include <algorithm>
#include <vector>

#include "cobalt/cssom/computed_style.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/anonymous_block_box.h"
#include "cobalt/layout/text_box.h"
#include "cobalt/layout/used_style.h"

namespace cobalt {
namespace layout {

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

FlexContainerBox::~FlexContainerBox() {}

void FlexContainerBox::DetermineAvailableSpace(
    const LayoutParams& layout_params, bool main_direction_is_horizontal,
    bool width_depends_on_containing_block,
    const base::Optional<LayoutUnit>& maybe_width,
    bool height_depends_on_containing_block,
    const base::Optional<LayoutUnit>& maybe_height) {
  // Line Length Determination:
  //   https://www.w3.org/TR/css-flexbox-1/#line-sizing
  // 2. Determine the available main and cross space for the flex items.
  base::Optional<LayoutUnit> main_space;
  base::Optional<LayoutUnit> cross_space;
  bool main_space_depends_on_containing_block;

  base::Optional<LayoutUnit> min_width = GetUsedMinWidthIfNotAuto(
      computed_style(), layout_params.containing_block_size, NULL);
  base::Optional<LayoutUnit> max_width = GetUsedMaxWidthIfNotNone(
      computed_style(), layout_params.containing_block_size, NULL);
  base::Optional<LayoutUnit> min_height = GetUsedMinHeightIfNotAuto(
      computed_style(), layout_params.containing_block_size);
  base::Optional<LayoutUnit> max_height = GetUsedMaxHeightIfNotNone(
      computed_style(), layout_params.containing_block_size);

  // For each dimension, if that dimension of the flex container's content box
  // is a definite size, use that.
  if (main_direction_is_horizontal) {
    bool freeze_main_space =
        layout_params.freeze_width || layout_params.shrink_to_fit_width_forced;
    bool freeze_cross_space = layout_params.freeze_height;
    main_space_depends_on_containing_block =
        width_depends_on_containing_block && (!freeze_main_space);
    main_space = maybe_width;
    cross_space = maybe_height;
    min_main_space_ = min_width;
    max_main_space_ = max_width;
    min_cross_space_ = min_height;
    max_cross_space_ = max_height;

    // If that dimension of the flex container is being sized under a min or
    // max-content constraint, the available space in that dimension is that
    // constraint.
    if (freeze_main_space) {
      main_space = width();
    }
    if (freeze_cross_space) {
      cross_space = height();
    }
  } else {
    bool freeze_main_space = layout_params.freeze_height;
    bool freeze_cross_space =
        layout_params.freeze_height || layout_params.shrink_to_fit_width_forced;
    main_space_depends_on_containing_block =
        height_depends_on_containing_block && (!freeze_main_space);
    main_space = maybe_height;
    cross_space = maybe_width;
    min_main_space_ = min_height;
    max_main_space_ = max_height;
    min_cross_space_ = min_width;
    max_cross_space_ = max_width;

    // If that dimension of the flex container is being sized under a min or
    // max-content constraint, the available space in that dimension is that
    // constraint.
    if (freeze_main_space) {
      main_space = height();
    }
    if (freeze_cross_space) {
      cross_space = width();
    }
  }

  if (GetLevel() == kBlockLevel) {
    if (main_direction_is_horizontal) {
      if (!main_space && main_space_depends_on_containing_block) {
        // Otherwise, subtract the flex container's margin, border, and padding
        // from the space available to the flex container in that dimension and
        // use that value.
        base::Optional<LayoutUnit> margin_main_start =
            GetUsedMarginLeftIfNotAuto(computed_style(),
                                       layout_params.containing_block_size);
        base::Optional<LayoutUnit> margin_main_end =
            GetUsedMarginRightIfNotAuto(computed_style(),
                                        layout_params.containing_block_size);
        main_space = layout_params.containing_block_size.width() -
                     margin_main_start.value_or(LayoutUnit()) -
                     margin_main_end.value_or(LayoutUnit()) -
                     border_left_width() - border_right_width() -
                     padding_left() - padding_right();
      }
    } else {
      if (!cross_space) {
        // Otherwise, subtract the flex container's margin, border, and padding
        // from the space available to the flex container in that dimension and
        // use that value.
        base::Optional<LayoutUnit> margin_cross_start =
            GetUsedMarginLeftIfNotAuto(computed_style(),
                                       layout_params.containing_block_size);
        base::Optional<LayoutUnit> margin_cross_end =
            GetUsedMarginRightIfNotAuto(computed_style(),
                                        layout_params.containing_block_size);
        cross_space = layout_params.containing_block_size.width() -
                      margin_cross_start.value_or(LayoutUnit()) -
                      margin_cross_end.value_or(LayoutUnit()) -
                      border_left_width() - border_right_width() -
                      padding_left() - padding_right();
      }
    }
  }

  main_space_ = main_space;
  cross_space_ = cross_space;
}

// From |Box|.
void FlexContainerBox::UpdateContentSizeAndMargins(
    const LayoutParams& layout_params) {
  // Flex layout works with the flex items in order-modified document order, not
  // their original document order.
  //   https://www.w3.org/TR/css-flexbox-1/#layout-algorithm
  EnsureBoxesAreInOrderModifiedDocumentOrder();

  bool main_direction_is_horizontal = MainDirectionIsHorizontal();

  // Algorithm for Flex Layout:
  //   https://www.w3.org/TR/css-flexbox-1/#layout-algorithm

  // Initial Setup:
  // 1. Generate anonymous flex items.
  // This is performed during box generation.

  // Line Length Determination:
  //   https://www.w3.org/TR/css-flexbox-1/#line-sizing
  // 2. Determine the available main and cross space for the flex items.
  //      https://www.w3.org/TR/css-flexbox-1/#algo-available

  bool width_depends_on_containing_block;
  base::Optional<LayoutUnit> maybe_width = GetUsedWidthIfNotAuto(
      computed_style(), layout_params.containing_block_size,
      &width_depends_on_containing_block);
  bool height_depends_on_containing_block;
  base::Optional<LayoutUnit> maybe_height = GetUsedHeightIfNotAuto(
      computed_style(), layout_params.containing_block_size,
      &height_depends_on_containing_block);

  DetermineAvailableSpace(layout_params, main_direction_is_horizontal,
                          width_depends_on_containing_block, maybe_width,
                          height_depends_on_containing_block, maybe_height);

  // 3. Determine the flex base size and hypothetical main size of each item.
  //      https://www.w3.org/TR/css-flexbox-1/#algo-main-item
  LayoutUnit main_space = main_space_.value_or(LayoutUnit());
  LayoutUnit cross_space = cross_space_.value_or(LayoutUnit());
  SizeLayoutUnit available_space(
      main_direction_is_horizontal ? main_space : cross_space,
      main_direction_is_horizontal ? cross_space : main_space);

  LayoutParams child_layout_params;
  child_layout_params.containing_block_size = available_space;

  FlexFormattingContext flex_formatting_context(
      child_layout_params, main_direction_is_horizontal, DirectionIsReversed());

  std::vector<std::unique_ptr<FlexItem>> items;
  items.reserve(child_boxes().size());

  for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
       child_box_iterator != child_boxes().end(); ++child_box_iterator) {
    Box* child_box = *child_box_iterator;
    if (!child_box->IsAbsolutelyPositioned()) {
      flex_formatting_context.UpdateRect(child_box);

      auto item = FlexItem::Create(child_box, main_direction_is_horizontal);
      item->DetermineFlexBaseSize(main_space_,
                                  layout_params.shrink_to_fit_width_forced);
      item->DetermineHypotheticalMainSize(
          child_layout_params.containing_block_size);
      items.emplace_back(std::move(item));
    }
  }

  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);

  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 (IsAbsolutelyPositioned()) {
    UpdateWidthAssumingAbsolutelyPositionedBox(
        layout_params.containing_block_size.width(), maybe_left, maybe_right,
        maybe_width, maybe_margin_left, maybe_margin_right, maybe_height);

    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);

    UpdateHeightAssumingAbsolutelyPositionedBox(
        layout_params.containing_block_size.height(), maybe_top, maybe_bottom,
        maybe_height, maybe_margin_top, maybe_margin_bottom,
        flex_formatting_context);
  }

  LayoutUnit main_size = LayoutUnit();
  // 4. Determine the main size of the flex container using the rules of the
  // formatting context in which it participates.
  if (main_direction_is_horizontal) {
    if (!layout_params.freeze_width) {
      UpdateContentWidthAndMargins(
          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, main_space_, cross_space_);
    }
    main_size = width();
  } else {
    if (!layout_params.freeze_height) {
      main_size =
          main_space_.value_or(flex_formatting_context.fit_content_main_size());
    } else {
      main_size = height();
    }
  }

  if (max_main_space_ && main_size > *max_main_space_) {
    main_size = *max_main_space_;
  }
  if (min_main_space_ && main_size < *min_main_space_) {
    main_size = *min_main_space_;
  }

  flex_formatting_context.SetContainerMainSize(main_size);

  // Main Size Determination:
  // 5. Collect flex items into flex lines.
  flex_formatting_context.set_multi_line(ContainerIsMultiLine());
  for (auto& item : items) {
    DCHECK(!item->box()->IsAbsolutelyPositioned());
    flex_formatting_context.CollectItemIntoLine(main_size, std::move(item));
  }

  if (main_direction_is_horizontal) {
    set_width(main_size);
  } else {
    if (!main_space_) {
      // For vertical containers with indefinite main space, us the fit content
      // main size. Note: For horizontal containers, this sizing is already
      // handled by UpdateContentWidthAndMargins().
      main_size = flex_formatting_context.fit_content_main_size();
    }
    set_height(main_size);
  }

  // Perform remaining steps of the layout of the items.
  flex_formatting_context.ResolveFlexibleLengthsAndCrossSizes(
      cross_space_, min_cross_space_, max_cross_space_,
      computed_style()->align_content());

  if (main_direction_is_horizontal) {
    set_height(flex_formatting_context.cross_size());
  } else {
    set_width(flex_formatting_context.cross_size());
  }

  set_margin_left(maybe_margin_left.value_or(LayoutUnit()));
  set_margin_right(maybe_margin_right.value_or(LayoutUnit()));
  set_margin_top(maybe_margin_top.value_or(LayoutUnit()));
  set_margin_bottom(maybe_margin_bottom.value_or(LayoutUnit()));

  UpdateRectOfPositionedChildBoxes(child_layout_params, layout_params);

  if (items.empty()) {
    baseline_ = GetPaddingBoxHeight() + border_bottom_width() + margin_bottom();
  } else {
    baseline_ = flex_formatting_context.GetBaseline();
  }
}

WrapResult FlexContainerBox::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());
  // Wrapping is not allowed until the line's existence is justified, meaning
  // that wrapping cannot occur before the box. Given that this box cannot be
  // split, no wrappable point is available.
  if (!is_line_existence_justified) {
    return kWrapResultNoWrap;
  }

  return (GetLevel() == kInlineLevel) ? kWrapResultWrapBefore
                                      : kWrapResultNoWrap;
}

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

void FlexContainerBox::SetShouldCollapseLeadingWhiteSpace(
    bool should_collapse_leading_white_space) {
  DCHECK_EQ(kInlineLevel, GetLevel());
}

void FlexContainerBox::SetShouldCollapseTrailingWhiteSpace(
    bool should_collapse_trailing_white_space) {
  DCHECK_EQ(kInlineLevel, GetLevel());
}

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

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

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

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

bool FlexContainerBox::AffectsBaselineInBlockFormattingContext() const {
  return true;
}

LayoutUnit FlexContainerBox::GetBaselineOffsetFromTopMarginEdge() const {
  return GetContentBoxOffsetFromMarginBox().y() + baseline_;
}

// From |ContainerBox|.
scoped_refptr<ContainerBox> FlexContainerBox::TrySplitAtEnd() {
  return scoped_refptr<ContainerBox>();
}

bool FlexContainerBox::TryAddChild(const scoped_refptr<Box>& child_box) {
  AddChild(child_box);
  return true;
}

void FlexContainerBox::AddChild(const scoped_refptr<Box>& child_box) {
  TextBox* text_box = child_box->AsTextBox();
  switch (child_box->GetLevel()) {
    case kBlockLevel:
      PushBackDirectChild(child_box);
      break;
    case kInlineLevel:
      if (text_box && !text_box->HasNonCollapsibleText()) {
        // Text boxes with only white space are not rendered, just as if
        // its text nodes were 'display:none'.
        //   https://www.w3.org/TR/css-flexbox-1/#flex-items
        return;
      }
      // An inline formatting context required,
      // add a child to an anonymous block box.
      GetOrAddAnonymousBlockBox()->AddInlineLevelChild(child_box);
      break;
  }
}

// From |Box|.
bool FlexContainerBox::IsTransformable() const { return true; }

bool FlexContainerBox::MainDirectionIsHorizontal() const {
  auto flex_direction = computed_style()->flex_direction();
  bool reverse_direction =
      flex_direction == cssom::KeywordValue::GetRowReverse() ||
      flex_direction == cssom::KeywordValue::GetColumnReverse();
  bool main_direction_is_horizontal =
      flex_direction == cssom::KeywordValue::GetRow() ||
      flex_direction == cssom::KeywordValue::GetRowReverse();

  // Ensure that all values for flex-direction are handled.
  DCHECK(main_direction_is_horizontal ^
         (flex_direction == cssom::KeywordValue::GetColumn() ||
          flex_direction == cssom::KeywordValue::GetColumnReverse()));

  DCHECK(reverse_direction ^
         (flex_direction == cssom::KeywordValue::GetRow() ||
          flex_direction == cssom::KeywordValue::GetColumn()));

  return main_direction_is_horizontal;
}

bool FlexContainerBox::DirectionIsReversed() const {
  auto flex_direction = computed_style()->flex_direction();
  bool reverse_direction =
      flex_direction == cssom::KeywordValue::GetRowReverse() ||
      flex_direction == cssom::KeywordValue::GetColumnReverse();

  // Ensure that all values for flex-direction are handled.
  DCHECK(reverse_direction ^
         (flex_direction == cssom::KeywordValue::GetRow() ||
          flex_direction == cssom::KeywordValue::GetColumn()));

  return reverse_direction;
}

bool FlexContainerBox::ContainerIsMultiLine() const {
  auto flex_wrap = computed_style()->flex_wrap();
  bool container_is_multiline =
      flex_wrap == cssom::KeywordValue::GetWrap() ||
      flex_wrap == cssom::KeywordValue::GetWrapReverse();

  // Ensure that all values for flex-wrap are handled.
  DCHECK(container_is_multiline ^
         (flex_wrap == cssom::KeywordValue::GetNowrap()));

  return container_is_multiline;
}

namespace {
// Return true if a is ordered before b.
bool CompareBoxOrder(const scoped_refptr<const Box>& a,
                     const scoped_refptr<const Box>& b) {
  int order_a = a->IsAbsolutelyPositioned() ? 0 : a->GetOrder();
  int order_b = b->IsAbsolutelyPositioned() ? 0 : b->GetOrder();
  return order_a < order_b;
}
}  // namespace

void FlexContainerBox::EnsureBoxesAreInOrderModifiedDocumentOrder() {
  // A flex container lays out its content in order-modified document order.
  // Items with the same ordinal group are laid out in the order they appear in
  // the source document. Absolutely-positioned children of a flex container
  // are treated as having 'order: 0'.
  //   https://www.w3.org/TR/css-flexbox-1/#order-modified-document-order

  // Note std::sort and std::qsort have undefined order of equal elements, so
  // they can only be used when being careful to not compare only by 'order'
  // value. However, since std::stable_sort does preserve the order of
  // equivalent elements, that can be used directly.
  std::stable_sort(child_boxes_.begin(), child_boxes_.end(), CompareBoxOrder);
}

AnonymousBlockBox* FlexContainerBox::GetLastChildAsAnonymousBlockBox() {
  return NULL;
}

AnonymousBlockBox* FlexContainerBox::GetOrAddAnonymousBlockBox() {
  AnonymousBlockBox* anonymous_block_box = GetLastChildAsAnonymousBlockBox();
  // If either the last box is not an anonymous block box, or the anonymous
  // block box already has a trailing line break and can't accept any additional
  // children, then create a new anonymous block box.
  if (anonymous_block_box == NULL ||
      anonymous_block_box->HasTrailingLineBreak()) {
    // TODO: Determine which animations to propagate to the anonymous block box,
    //       instead of none at all.
    scoped_refptr<cssom::CSSComputedStyleDeclaration>
        new_computed_style_declaration =
            new cssom::CSSComputedStyleDeclaration();
    new_computed_style_declaration->SetData(
        GetComputedStyleOfAnonymousBox(css_computed_style_declaration()));
    new_computed_style_declaration->set_animations(
        new web_animations::AnimationSet());
    scoped_refptr<AnonymousBlockBox> new_anonymous_block_box(
        new AnonymousBlockBox(new_computed_style_declaration, base_direction(),
                              used_style_provider(), layout_stat_tracker()));
    anonymous_block_box = new_anonymous_block_box.get();
    PushBackDirectChild(new_anonymous_block_box);
  }
  return anonymous_block_box;
}

std::unique_ptr<FormattingContext>
FlexContainerBox::UpdateRectOfInFlowChildBoxes(
    const LayoutParams& child_layout_params) {
  std::unique_ptr<FlexFormattingContext> flex_formatting_context(
      new FlexFormattingContext(child_layout_params,
                                MainDirectionIsHorizontal(),
                                DirectionIsReversed()));
  for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
       child_box_iterator != child_boxes().end(); ++child_box_iterator) {
    Box* child_box = *child_box_iterator;
    if (!child_box->IsAbsolutelyPositioned()) {
      flex_formatting_context->UpdateRect(child_box);
    }
  }
  return std::unique_ptr<FormattingContext>(flex_formatting_context.release());
}

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

BlockLevelFlexContainerBox::~BlockLevelFlexContainerBox() {}

Box::Level BlockLevelFlexContainerBox::GetLevel() const { return kBlockLevel; }

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

#ifdef COBALT_BOX_DUMP_ENABLED
void BlockLevelFlexContainerBox::DumpClassName(std::ostream* stream) const {
  *stream << "BlockLevelFlexContainerBox ";
}
#endif  // COBALT_BOX_DUMP_ENABLED

InlineLevelFlexContainerBox::InlineLevelFlexContainerBox(
    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
        css_computed_style_declaration,
    BaseDirection base_direction, const scoped_refptr<Paragraph>& paragraph,
    int32 text_position, UsedStyleProvider* used_style_provider,
    LayoutStatTracker* layout_stat_tracker)
    : FlexContainerBox(css_computed_style_declaration, base_direction,
                       used_style_provider, layout_stat_tracker),
      paragraph_(paragraph),
      text_position_(text_position) {}

InlineLevelFlexContainerBox::~InlineLevelFlexContainerBox() {}

Box::Level InlineLevelFlexContainerBox::GetLevel() const {
  return kInlineLevel;
}

base::Optional<int> InlineLevelFlexContainerBox::GetBidiLevel() const {
  return paragraph_->GetBidiLevel(text_position_);
}

#ifdef COBALT_BOX_DUMP_ENABLED
void InlineLevelFlexContainerBox::DumpClassName(std::ostream* stream) const {
  *stream << "InlineLevelFlexContainerBox ";
}
#endif  // COBALT_BOX_DUMP_ENABLED

}  // namespace layout
}  // namespace cobalt
