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

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

  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 (!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.
    if (main_direction_is_horizontal) {
      if (GetLevel() == kBlockLevel) {
        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 (GetLevel() == kInlineLevel) {
        base::Optional<LayoutUnit> margin_main_start =
            GetUsedMarginTopIfNotAuto(computed_style(),
                                      layout_params.containing_block_size);
        base::Optional<LayoutUnit> margin_main_end =
            GetUsedMarginBottomIfNotAuto(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_top_width() - border_bottom_width() -
                     padding_top() - padding_bottom();
      }
    }
  }

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

  if (cross_space) {
    if (max_cross_space_ && *cross_space_ > *max_cross_space_) {
      cross_space = max_cross_space_;
    }
    if (min_cross_space_ && *cross_space < *min_cross_space_) {
      cross_space = *min_cross_space_;
    }
  }

  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
  DetermineAvailableSpace(layout_params, main_direction_is_horizontal);

  // 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(child_layout_params, main_space_,
                                  layout_params.shrink_to_fit_width_forced);
      item->DetermineHypotheticalMainSize(
          child_layout_params.containing_block_size);
      items.emplace_back(std::move(item));
    }
  }

  // 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) {
      bool width_depends_on_containing_block = true;
      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_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_);
    }
    flex_formatting_context.set_main_size(width());
  } else {
    if (!layout_params.freeze_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);
      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);

      UpdateContentHeightAndMargins(layout_params.containing_block_size,
                                    maybe_top, maybe_bottom, maybe_margin_top,
                                    maybe_margin_bottom, main_space_);
    }
    flex_formatting_context.set_main_size(height());
  }

  LayoutUnit main_size = flex_formatting_context.main_size();
  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.set_main_size(main_size);

  if (main_direction_is_horizontal) {
    set_width(main_size);
  } else {
    set_height(main_size);
  }
  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(std::move(item));
  }

  // 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());
  }

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

  set_margin_left(maybe_margin_left.value_or(LayoutUnit()));
  set_margin_right(maybe_margin_right.value_or(LayoutUnit()));

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

  set_margin_top(maybe_margin_top.value_or(LayoutUnit()));
  set_margin_bottom(maybe_margin_bottom.value_or(LayoutUnit()));
  if (child_boxes().empty()) {
    baseline_ = GetBorderBoxHeight();
  } 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) {
  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 child_boxes().empty() ? NULL
                               : child_boxes().back()->AsAnonymousBlockBox();
}

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
