/*
 * 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
