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

#include <algorithm>
#include <list>
#include <vector>

#include "cobalt/cssom/css_computed_style_data.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/used_style.h"

namespace cobalt {
namespace layout {

FlexLine::FlexLine(const LayoutParams& layout_params,
                   bool main_direction_is_horizontal,
                   bool direction_is_reversed, LayoutUnit main_size)
    : layout_params_(layout_params),
      main_direction_is_horizontal_(main_direction_is_horizontal),
      direction_is_reversed_(direction_is_reversed),
      main_size_(main_size) {
  items_outer_main_size_ = LayoutUnit(0);
}

bool FlexLine::CanAddItem(const FlexItem& item) const {
  LayoutUnit outer_main_size =
      item.hypothetical_main_size() + item.GetContentToMarginMainAxis();
  LayoutUnit next_main_size = items_outer_main_size_ + outer_main_size;
  if (!items_.empty() && next_main_size > main_size_) {
    return false;
  }
  return true;
}

void FlexLine::AddItem(std::unique_ptr<FlexItem>&& item) {
  LayoutUnit outer_main_size =
      item->hypothetical_main_size() + item->GetContentToMarginMainAxis();

  items_outer_main_size_ += outer_main_size;
  items_.emplace_back(std::move(item));
}

void FlexLine::ResolveFlexibleLengthsAndCrossSize() {
  // Algorithm for resolving flexible lengths:
  //   https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths

  // 1. Determine the used flex factor.
  // If the sum is less than the flex container's inner main size, use the flex
  // grow factor.
  flex_factor_grow_ = items_outer_main_size_ < main_size_;

  // 2. Size inflexible items.
  // 3. Calculate initial free space.
  LayoutUnit flex_space = LayoutUnit();
  LayoutUnit frozen_space = LayoutUnit();
  LayoutUnit scaled_flex_shrink_factor_sum = LayoutUnit();

  // Items are removed from this container in random order.
  std::list<FlexItem*> flexible_items;
  for (auto& item : items_) {
    item->DetermineFlexFactor(flex_factor_grow_);
    // 2. Size inflexible items:
    // - any item that has a flex factor of zero.
    // - if using the flex grow factor: any item that has a flex base size
    //   greater than its hypothetical main size.
    // - if using the flex shrink factor: any item that has a flex base size
    //   smaller than its hypothetical main size.
    LayoutUnit hypothetical_main_size = item->hypothetical_main_size();

    if (0 == item->flex_factor() ||
        (flex_factor_grow_ &&
         (item->flex_base_size() > hypothetical_main_size)) ||
        (!flex_factor_grow_ &&
         (item->flex_base_size() < hypothetical_main_size))) {
      // Freeze, setting its target main size to its hypothetical main size.
      base::Optional<LayoutUnit> content_based_minimum_size =
          item->GetContentBasedMinimumSize(
              layout_params_.containing_block_size);
      if (content_based_minimum_size.has_value()) {
        hypothetical_main_size =
            std::max(hypothetical_main_size, *content_based_minimum_size);
      }
      item->set_target_main_size(hypothetical_main_size);

      // 3. Calculate initial free space.
      // For frozen items, use their outer target main size;
      frozen_space +=
          item->GetContentToMarginMainAxis() + item->target_main_size();
    } else {
      flexible_items.push_back(item.get());

      // for other items, use their outer flex base size.
      item->set_flex_space(item->GetContentToMarginMainAxis() +
                           item->flex_base_size());
      item->set_target_main_size(item->hypothetical_main_size());
      flex_space += item->flex_space();

      // Precalculate the scaled flex shrink factor.
      // If using the flex shrink factor, for every unfrozen item on the line,
      if (!flex_factor_grow_) {
        // multiply its flex shrink factor by its inner flex base size.
        item->set_scaled_flex_shrink_factor(item->flex_base_size() *
                                            item->flex_factor());
        scaled_flex_shrink_factor_sum += item->scaled_flex_shrink_factor();
      }
    }
  }

  LayoutUnit initial_free_space = main_size_ - frozen_space - flex_space;

  // 4. Loop
  while (true) {
    // a. Check for flexible items.
    if (flexible_items.empty()) {
      // If all the flex items on the line are frozen, free space has been
      // distributed; exit this loop.
      break;
    }

    // b. Calculate the remaining free space.
    LayoutUnit remaining_free_space = main_size_ - frozen_space - flex_space;

    // If the sum of the unfrozen flex items' flex factors ...
    float unfrozen_flex_factor_sum = 0;
    for (auto& item : flexible_items) {
      unfrozen_flex_factor_sum += item->flex_factor();
    }

    // ... is less than one, multiply the initial free space by this sum.
    if (unfrozen_flex_factor_sum < 1.0f) {
      LayoutUnit free_space_magnitude =
          initial_free_space * unfrozen_flex_factor_sum;
      // If the magnitude of this value is less than the magnitude of the
      // remaining free space, use this as the remaining free space.
      if ((free_space_magnitude >= LayoutUnit() &&
           free_space_magnitude < remaining_free_space) ||
          (free_space_magnitude < LayoutUnit() &&
           free_space_magnitude > remaining_free_space)) {
        remaining_free_space = free_space_magnitude;
      }
    }

    // c. Distribute free space proportional to the flex factors.
    // If the remaining free space is zero, do nothing.
    if (remaining_free_space != LayoutUnit()) {
      if (flex_factor_grow_) {
        // If using the flex grow factor.
        for (auto& item : flexible_items) {
          // Find the ratio of the item's flex grow factor to the sum of the
          // flex grow factors of all unfrozen items on the line.
          float ratio = item->flex_factor() / unfrozen_flex_factor_sum;
          // Set the item's target main size to its flex base size plus a
          // fraction of the remaining free space proportional to the ratio.
          item->set_target_main_size(item->flex_base_size() +
                                     remaining_free_space * ratio);
        }
      } else {
        // If using the flex shrink factor,
        for (auto& item : flexible_items) {
          // Find the ratio of the item's scaled flex shrink factor to the sum
          // of the scaled flex shrink factors.
          float ratio = item->scaled_flex_shrink_factor().toFloat() /
                        scaled_flex_shrink_factor_sum.toFloat();
          // Set the item's target main size to its flex base size minus a
          // fraction of the absolute value of the remaining free space
          // proportional to the ratio.
          item->set_target_main_size(item->flex_base_size() +
                                     remaining_free_space * ratio);
        }
      }
    }

    // d. Fix min/max violations.
    // Clamp each non-frozen item's target main size by its used min and max
    // main sizes. and floor its content-box size at zero.
    LayoutUnit unclamped_size = LayoutUnit();
    LayoutUnit clamped_size = LayoutUnit();
    for (auto& item : flexible_items) {
      base::Optional<LayoutUnit> maybe_used_min_space;
      if (flex_factor_grow_) {
        maybe_used_min_space = item->GetUsedMinMainAxisSizeIfNotAuto(
            layout_params_.containing_block_size);
      } else {
        maybe_used_min_space = item->GetContentBasedMinimumSize(
            layout_params_.containing_block_size);
      }
      base::Optional<LayoutUnit> used_max_space =
          item->GetUsedMaxMainAxisSizeIfNotNone(
              layout_params_.containing_block_size);

      unclamped_size += item->target_main_size();
      if (maybe_used_min_space &&
          (item->target_main_size() < *maybe_used_min_space)) {
        item->set_target_main_size(*maybe_used_min_space);
        item->set_min_violation(true);
      } else if (used_max_space && item->target_main_size() > *used_max_space) {
        item->set_target_main_size(*used_max_space);
        item->set_max_violation(true);
      } else if (item->target_main_size() < LayoutUnit()) {
        item->set_target_main_size(LayoutUnit());
        item->set_min_violation(true);
      }
      clamped_size += item->target_main_size();
    }

    // e. Freeze over-flexed items.

    // If the total violation is zero, freeze all items.
    bool freeze_all = clamped_size == unclamped_size;
    // If the total violation is positive, freeze all the items with min
    // violations.
    bool freeze_min_violations = clamped_size > unclamped_size;
    // If the total violation is negative, freeze all the items with max
    // violations.
    bool freeze_max_violations = clamped_size < unclamped_size;
    // Otherwise, do nothing.
    if (!(freeze_all || freeze_min_violations || freeze_max_violations)) {
      continue;
    }

    // Freeze the items by removing them from flexible_items and adding their
    // outer main size to the frozen space.
    for (auto item_iterator = flexible_items.begin();
         item_iterator != flexible_items.end();) {
      auto current_iterator = item_iterator++;
      auto& item = *current_iterator;
      if (freeze_all || (freeze_min_violations && item->min_violation()) ||
          (freeze_max_violations && item->max_violation())) {
        frozen_space +=
            item->GetContentToMarginMainAxis() + item->target_main_size();
        flex_space -= item->flex_space();
        if (!flex_factor_grow_) {
          scaled_flex_shrink_factor_sum -= item->scaled_flex_shrink_factor();
        }
        flexible_items.erase(current_iterator);
      }
    }
    // f. return to the start of this loop.
  }
  items_outer_main_size_ = frozen_space;

  // 5. Set each item's used main size to its target main size.
  //   https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths
  // Also, algorithm for Flex Layout continued from step 7:
  //   https://www.w3.org/TR/css-flexbox-1/#layout-algorithm
  // Cross Size Determination:
  // 7. Determine the hypothetical cross size of each item
  // By performing layout with the used main size and the available space.
  for (auto& item : items_) {
    item->DetermineHypotheticalCrossSize(layout_params_);
  }
}

void FlexLine::CalculateCrossSize() {
  // Algorithm for Calculate the cross size of each flex line.
  //   https://www.w3.org/TR/css-flexbox-1/#algo-cross-line

  LayoutUnit max_baseline_to_bottom = LayoutUnit();
  LayoutUnit max_hypothetical_cross_size = LayoutUnit();
  for (auto& item : items_) {
    // 1. Collect all the flex items whose inline-axis is parallel to the
    // main-axis, whose align-self is baseline, and whose cross-axis margins
    // are both non-auto.
    if (main_direction_is_horizontal_ &&
        item->GetUsedAlignSelfPropertyValue() ==
            cssom::KeywordValue::GetBaseline() &&
        !item->MarginCrossStartIsAuto() && !item->MarginCrossEndIsAuto()) {
      // Find the largest of the distances between each item's baseline and its
      // hypothetical outer cross-start edge,
      LayoutUnit baseline_to_top =
          item->box()->GetBaselineOffsetFromTopMarginEdge();
      max_baseline_to_top_ = std::max(
          max_baseline_to_top_.value_or(LayoutUnit()), baseline_to_top);
      // and the largest of the distances between each item's baseline and its
      // hypothetical outer cross-end edge,
      LayoutUnit baseline_to_bottom = item->box()->height() - baseline_to_top;
      max_baseline_to_bottom =
          std::max(max_baseline_to_bottom, baseline_to_bottom);
    } else {
      // 2. Among all the items not collected by the previous step, find the
      // largest outer hypothetical cross size.
      LayoutUnit hypothetical_cross_size = item->GetMarginBoxCrossSize();
      if (hypothetical_cross_size > max_hypothetical_cross_size) {
        max_hypothetical_cross_size = hypothetical_cross_size;
      }
    }
  }
  // ... and sum these two values.
  LayoutUnit max_baseline_cross_size =
      max_baseline_to_top_.value_or(LayoutUnit()) + max_baseline_to_bottom;

  // 3. The used cross-size of the flex line is the largest of the numbers
  // found in the previous two steps and zero.
  cross_size_ = std::max(max_hypothetical_cross_size, max_baseline_cross_size);
}

void FlexLine::DetermineUsedCrossSizes(LayoutUnit container_cross_size) {
  // 11. Determine the used cross size of each flex item->
  //   https://www.w3.org/TR/css-flexbox-1/#algo-stretch
  SizeLayoutUnit containing_block_size(LayoutUnit(), container_cross_size);
  for (auto& item : items_) {
    // If a flex item has align-self: stretch,
    // its computed cross size property is auto,
    // and neither of its cross-axis margins are auto,
    if (item->GetUsedAlignSelfPropertyValue() ==
            cssom::KeywordValue::GetStretch() &&
        item->CrossSizeIsAuto() && !item->MarginCrossStartIsAuto() &&
        !item->MarginCrossEndIsAuto()) {
      // The used outer cross size is the used cross size of its flex line,
      // clamped according to the item's used min and max cross sizes.
      LayoutUnit cross_size = cross_size_ - item->GetContentToMarginCrossAxis();
      base::Optional<LayoutUnit> min_cross_size =
          item->GetUsedMinCrossAxisSizeIfNotAuto(containing_block_size);
      if (min_cross_size && (*min_cross_size > cross_size)) {
        cross_size = *min_cross_size;
      }
      base::Optional<LayoutUnit> max_cross_size =
          item->GetUsedMaxCrossAxisSizeIfNotNone(containing_block_size);
      if (max_cross_size && *max_cross_size < cross_size) {
        cross_size = *max_cross_size;
      }
      item->SetCrossSize(cross_size);

      // TODO: If the flex item has align-self: stretch, redo layout for its
      // contents, treating this used size as its definite cross size so that
      // percentage-sized children can be resolved.
    }
  }
}

void FlexLine::SetMainAxisPosition(LayoutUnit pos, FlexItem* item) {
  if (direction_is_reversed_) {
    item->SetMainAxisStart(main_size_ - pos - item->GetMarginBoxMainSize());
  } else {
    item->SetMainAxisStart(pos);
  }
}

void FlexLine::DoMainAxisAlignment() {
  // Algorithm for main axis alignment:
  //   https://www.w3.org/TR/css-flexbox-1/#main-alignment
  // 12. Distribute any remaining free space.
  //   https://www.w3.org/TR/css-flexbox-1/#algo-main-align

  // If the remaining free space is positive and at least one main-axis margin
  // on this line is auto, distribute the free space equally among these
  // margins.
  std::vector<bool> auto_margins(items_.size());
  int auto_margin_count = 0;
  int margin_idx = 0;
  for (auto& item : items_) {
    bool auto_main_start = item->MarginMainStartIsAuto();
    bool auto_main_end = item->MarginMainEndIsAuto();
    auto_margins[margin_idx++] = auto_main_start;
    auto_margins[margin_idx++] = auto_main_end;
    auto_margin_count += (auto_main_start ? 1 : 0) + (auto_main_end ? 1 : 0);
  }
  LayoutUnit leftover_free_space = main_size_ - items_outer_main_size_;
  if (auto_margin_count > 0) {
    LayoutUnit free_space_between = leftover_free_space / auto_margin_count;

    margin_idx = 0;
    LayoutUnit pos = LayoutUnit();
    for (auto& item : items_) {
      pos += auto_margins[margin_idx++] ? free_space_between : LayoutUnit();
      LayoutUnit main_size = item->GetMarginBoxMainSize();
      SetMainAxisPosition(pos, item.get());
      pos += main_size;
      pos += auto_margins[margin_idx++] ? free_space_between : LayoutUnit();
    }

    return;
  }

  DCHECK(!items_.empty());

  // Align the items along the main-axis per justify-content.
  const scoped_refptr<cobalt::cssom::PropertyValue>& justify_content =
      items_.front()->GetUsedJustifyContentPropertyValue();

  bool leftover_free_space_is_negative = leftover_free_space < LayoutUnit();

  if (justify_content == cssom::KeywordValue::GetFlexStart() ||
      (leftover_free_space_is_negative &&
       justify_content == cssom::KeywordValue::GetSpaceBetween())) {
    // Flex items are packed toward the start of the line.
    //   https://www.w3.org/TR/css-flexbox-1/#valdef-justify-content-flex-start
    // If the leftover free-space is negative, space-between is identical to
    // flex-start.
    //   https://www.w3.org/TR/css-flexbox-1/#valdef-justify-content-space-between
    LayoutUnit pos = LayoutUnit();
    for (auto& item : items_) {
      LayoutUnit main_size = item->GetMarginBoxMainSize();
      SetMainAxisPosition(pos, item.get());
      pos += main_size;
    }
  } else if (justify_content == cssom::KeywordValue::GetFlexEnd()) {
    // Flex items are packed toward the end of the line.
    //   https://www.w3.org/TR/css-flexbox-1/#valdef-justify-content-flex-end
    LayoutUnit pos = main_size_;
    for (auto item_iterator = items_.rbegin(); item_iterator != items_.rend();
         ++item_iterator) {
      auto& item = *item_iterator;
      LayoutUnit main_size = item->GetMarginBoxMainSize();
      pos -= main_size;
      SetMainAxisPosition(pos, item.get());
    }
  } else if (justify_content == cssom::KeywordValue::GetCenter() ||
             (leftover_free_space_is_negative &&
              justify_content == cssom::KeywordValue::GetSpaceAround())) {
    // Flex items are packed toward the center of the line.
    //   https://www.w3.org/TR/css-flexbox-1/#valdef-justify-content-center
    // If the leftover free-space is negative, space-around is identical to
    // center.
    //   https://www.w3.org/TR/css-flexbox-1/#valdef-justify-content-space-around
    LayoutUnit pos = leftover_free_space / 2;
    for (auto& item : items_) {
      LayoutUnit main_size = item->GetMarginBoxMainSize();
      SetMainAxisPosition(pos, item.get());
      pos += main_size;
    }
  } else if (justify_content == cssom::KeywordValue::GetSpaceBetween()) {
    // Flex items are evenly distributed in the line.
    //   https://www.w3.org/TR/css-flexbox-1/#valdef-justify-content-space-between
    LayoutUnit free_space_between =
        (items_.size() < 2)
            ? LayoutUnit()
            : leftover_free_space / static_cast<int>(items_.size() - 1);
    LayoutUnit pos = LayoutUnit();
    for (auto& item : items_) {
      LayoutUnit main_size = item->GetMarginBoxMainSize();
      SetMainAxisPosition(pos, item.get());
      pos += main_size + free_space_between;
    }
  } else if (justify_content == cssom::KeywordValue::GetSpaceAround()) {
    // Flex items are evenly distributed in the line, with half-size spaces on
    // either end.
    //   https://www.w3.org/TR/css-flexbox-1/#valdef-justify-content-space-around
    LayoutUnit free_space_between =
        leftover_free_space / static_cast<int>(items_.size());
    LayoutUnit free_space_before = free_space_between / 2;
    LayoutUnit pos = LayoutUnit();

    for (auto& item : items_) {
      LayoutUnit main_size = item->GetMarginBoxMainSize();
      SetMainAxisPosition(pos + free_space_before, item.get());
      pos += main_size + free_space_between;
    }
  } else {
    // Added as sanity check for unsupported values.
    NOTREACHED();
  }
}

void FlexLine::DoCrossAxisAlignment(LayoutUnit line_cross_axis_start) {
  // Algorithm for cross axis alignment:
  //   https://www.w3.org/TR/css-flexbox-1/#cross-alignment
  // 13. Resolve cross-axis auto margins.
  // 14. Align all flex items along the cross-axis per align-self.
  for (auto& item : items_) {
    LayoutUnit cross_axis_start = LayoutUnit();

    bool auto_margin_cross_start = item->MarginCrossStartIsAuto();
    bool auto_margin_cross_end = item->MarginCrossEndIsAuto();
    LayoutUnit cross_size = item->GetMarginBoxCrossSize();
    if (auto_margin_cross_start || auto_margin_cross_end) {
      if (auto_margin_cross_start) {
        cross_axis_start =
            (cross_size_ - cross_size) / (auto_margin_cross_end ? 2 : 1);
      }
    } else {
      const auto& align_self = item->GetUsedAlignSelfPropertyValue();
      // Only flex-end, center, and baseline can result in a cross_axis_start
      // that is not aligned to the line cross start edge.
      if (align_self == cssom::KeywordValue::GetFlexEnd()) {
        cross_axis_start = cross_size_ - cross_size;
      } else if (align_self == cssom::KeywordValue::GetCenter()) {
        cross_axis_start = (cross_size_ - cross_size) / 2;
      } else if (align_self == cssom::KeywordValue::GetBaseline()) {
        if (main_direction_is_horizontal_ && max_baseline_to_top_.has_value()) {
          LayoutUnit baseline_to_top =
              item->box()->GetBaselineOffsetFromTopMarginEdge();
          cross_axis_start = *max_baseline_to_top_ - baseline_to_top;
        }
      } else {
        DCHECK((align_self == cssom::KeywordValue::GetFlexStart()) ||
               (align_self == cssom::KeywordValue::GetStretch()));
      }
    }
    item->SetCrossAxisStart(line_cross_axis_start + cross_axis_start);
  }
}

LayoutUnit FlexLine::GetBaseline() {
  if (max_baseline_to_top_.has_value()) {
    return *max_baseline_to_top_;
  }
  LayoutUnit baseline = cross_size_;
  if (!items_.empty()) {
    Box* box = items_.front()->box();
    baseline = box->top() + box->GetBaselineOffsetFromTopMarginEdge();
  }
  return baseline;
}

}  // namespace layout
}  // namespace cobalt
