// Copyright 2015 Google Inc. 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/inline_formatting_context.h"

#include <algorithm>

#include "base/logging.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/line_box.h"
#include "cobalt/layout/used_style.h"

namespace cobalt {
namespace layout {

InlineFormattingContext::InlineFormattingContext(
    const scoped_refptr<cssom::PropertyValue>& line_height,
    const render_tree::FontMetrics& font_metrics,
    const LayoutParams& layout_params, BaseDirection base_direction,
    const scoped_refptr<cssom::PropertyValue>& text_align,
    const scoped_refptr<cssom::PropertyValue>& font_size,
    LayoutUnit text_indent_offset, LayoutUnit ellipsis_width)
    : line_height_(line_height),
      font_metrics_(font_metrics),
      layout_params_(layout_params),
      base_direction_(base_direction),
      text_align_(text_align),
      font_size_(font_size),
      text_indent_offset_(text_indent_offset),
      ellipsis_width_(ellipsis_width),
      line_count_(0) {
  CreateLineBox();
}

InlineFormattingContext::~InlineFormattingContext() {}

Box* InlineFormattingContext::TryAddChildAndMaybeWrap(Box* child_box) {
  // When an inline box exceeds the width of a line box, it is split into
  // several boxes and these boxes are distributed across several line boxes.
  //   https://www.w3.org/TR/CSS21/visuren.html#inline-formatting
  //
  // We tackle this problem one line at a time.

  Box* child_box_before_wrap = line_box_->TryAddChildAndMaybeWrap(child_box);
  // If |child_box_before_wrap| is non-NULL, then a line wrap has occurred and a
  // new line box must be created.
  if (child_box_before_wrap) {
    CreateLineBox();
  }
  return child_box_before_wrap;
}

void InlineFormattingContext::EndUpdates() {
  // Treat the end of child boxes almost as an explicit line break,
  // but don't create the new line box.
  DestroyLineBox();

  // The shrink-to-fit width is:
  // min(max(preferred minimum width, available width), preferred width).
  //   https://www.w3.org/TR/CSS21/visudet.html#float-width
  //
  // Naive solution of the above expression would require two layout passes:
  // one to calculate the "preferred minimum width" and another one to
  // calculate the "preferred width". It is possible to save one layout pass
  // taking into account that:
  //   - an exact value of "preferred width" does not matter if "available
  //     width" cannot acommodate it;
  //   - the inline formatting context has more than one line if and only if
  //     the "preferred width" is greater than the "available width";
  //   - "preferred minimum" and "preferred" widths are equal when an inline
  //     formatting context has only one line.
  set_shrink_to_fit_width(std::max(
      preferred_min_width_, line_count_ > 1
                                ? layout_params_.containing_block_size.width()
                                : LayoutUnit()));
}

const std::vector<math::Vector2dF>&
InlineFormattingContext::GetEllipsesCoordinates() const {
  return ellipses_coordinates_;
}

void InlineFormattingContext::CreateLineBox() {
  if (line_box_) {
    DestroyLineBox();
  }

  // "'Text-indent' only affects a line if it is the first formatted line of an
  // element."
  //   https://www.w3.org/TR/CSS21/text.html#propdef-text-indent
  LayoutUnit line_indent_offset =
      line_count_ == 0 ? text_indent_offset_ : LayoutUnit();

  // Line boxes are stacked with no vertical separation and they never
  // overlap.
  //   https://www.w3.org/TR/CSS21/visuren.html#inline-formatting
  line_box_ = make_scoped_ptr(
      new LineBox(auto_height(), false, line_height_, font_metrics_, true, true,
                  layout_params_, base_direction_, text_align_, font_size_,
                  line_indent_offset, ellipsis_width_));
}

void InlineFormattingContext::DestroyLineBox() {
  line_box_->EndUpdates();

  // The baseline of an "inline-block" is the baseline of its last line box
  // in the normal flow, unless it has no in-flow line boxes.
  //   https://www.w3.org/TR/CSS21/visudet.html#line-height
  if (line_box_->LineExists()) {
    ++line_count_;

    preferred_min_width_ =
        std::max(preferred_min_width_, line_box_->shrink_to_fit_width());

    // If "height" is "auto", the used value is the distance from box's top
    // content edge to the bottom edge of the last line box, if the box
    // establishes an inline formatting context with one or more lines.
    //   https://www.w3.org/TR/CSS21/visudet.html#normal-block
    set_auto_height(line_box_->top() + line_box_->height());

    set_baseline_offset_from_top_content_edge(
        line_box_->top() + line_box_->baseline_offset_from_top());

    if (line_box_->IsEllipsisPlaced()) {
      ellipses_coordinates_.push_back(line_box_->GetEllipsisCoordinates());
    }
  }

  line_box_.reset();
}

}  // namespace layout
}  // namespace cobalt
