/*
 * 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) {
  DCHECK(child_box->GetLevel() == Box::kInlineLevel);

  // 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::BeginEstimateStaticPosition(Box* child_box) {
  line_box_->BeginEstimateStaticPosition(child_box);
}

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
