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

#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/container_box.h"
#include "cobalt/layout/rect_layout_unit.h"
#include "cobalt/layout/size_layout_unit.h"

namespace cobalt {
namespace layout {

LayoutBoxes::LayoutBoxes() {}

LayoutBoxes::~LayoutBoxes() {}

LayoutBoxes::Type LayoutBoxes::type() const { return kLayoutLayoutBoxes; }

// Algorithm for GetClientRects:
//   https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-element-getclientrects
scoped_refptr<dom::DOMRectList> LayoutBoxes::GetClientRects() const {
  // 1. If the element on which it was invoked does not have an associated
  // layout box return an empty DOMRectList object and stop this algorithm.

  // 2. If the element has an associated SVG layout box return a DOMRectList
  // object containing a single DOMRect object that describes the bounding box
  // of the element as defined by the SVG specification, applying the transforms
  // that apply to the element and its ancestors.

  // 3. Return a DOMRectList object containing a list of DOMRect objects in
  // content order describing the bounding border boxes (including those with a
  // height or width of zero) with the following constraints:
  //  . Apply the transforms that apply to the element and its ancestors.
  //  . If the element on which the method was invoked has a computed value for
  //    the 'display' property of 'table' or 'inline-table' include both the
  //    table box and the caption box, if any, but not the anonymous container
  //    box.
  //  . Replace each anonymous block box with its child box(es) and repeat this
  //    until no anonymous block boxes are left in the final list.

  scoped_refptr<dom::DOMRectList> dom_rect_list(new dom::DOMRectList());
  for (Boxes::const_iterator box_iterator = boxes_.begin();
       box_iterator != boxes_.end(); ++box_iterator) {
    Box* box = *box_iterator;
    do {
      scoped_refptr<dom::DOMRect> dom_rect(new dom::DOMRect());

      // TODO: Take transforms into account and recurse into anonymous block
      // boxes. Our current clients don't currently rely on GetClientRects() to
      // do that.

      dom_rect->set_x(
          box->GetBorderBoxLeftEdge(false /*stop_at_transform*/).toFloat());
      dom_rect->set_y(
          box->GetBorderBoxTopEdge(false /*stop_at_transform*/).toFloat());
      SizeLayoutUnit box_size = box->GetBorderBoxSize();
      dom_rect->set_width(box_size.width().toFloat());
      dom_rect->set_height(box_size.height().toFloat());
      dom_rect_list->AppendDOMRect(dom_rect);

      box = box->GetSplitSibling();
    } while (box != NULL);
  }

  return dom_rect_list;
}

bool LayoutBoxes::IsInline() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()->computed_style()->display() ==
         cssom::KeywordValue::GetInline();
}

float LayoutBoxes::GetBorderEdgeLeft() const {
  return GetBoundingBorderRectangle().x();
}

float LayoutBoxes::GetBorderEdgeTop() const {
  return GetBoundingBorderRectangle().y();
}

float LayoutBoxes::GetBorderEdgeWidth() const {
  return GetBoundingBorderRectangle().width();
}

float LayoutBoxes::GetBorderEdgeHeight() const {
  return GetBoundingBorderRectangle().height();
}

float LayoutBoxes::GetBorderLeftWidth() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()->border_left_width().toFloat();
}

float LayoutBoxes::GetBorderTopWidth() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()->border_top_width().toFloat();
}

float LayoutBoxes::GetMarginEdgeWidth() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()->GetMarginBoxWidth().toFloat();
}

float LayoutBoxes::GetMarginEdgeHeight() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()->GetMarginBoxHeight().toFloat();
}

float LayoutBoxes::GetPaddingEdgeLeft() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()
      ->GetPaddingBoxLeftEdge(false /*stop_at_transform*/)
      .toFloat();
}

float LayoutBoxes::GetPaddingEdgeTop() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()
      ->GetPaddingBoxTopEdge(false /*stop_at_transform*/)
      .toFloat();
}

float LayoutBoxes::GetPaddingEdgeWidth() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()->GetPaddingBoxWidth().toFloat();
}

float LayoutBoxes::GetPaddingEdgeHeight() const {
  DCHECK(!boxes_.empty());
  return boxes_.front()->GetPaddingBoxHeight().toFloat();
}

void LayoutBoxes::InvalidateSizes() {
  for (Boxes::const_iterator box_iterator = boxes_.begin();
       box_iterator != boxes_.end(); ++box_iterator) {
    Box* box = *box_iterator;
    do {
      box->InvalidateUpdateSizeInputsOfBoxAndAncestors();
      box = box->GetSplitSibling();
    } while (box != NULL);
  }
}

void LayoutBoxes::InvalidateCrossReferences() {
  for (Boxes::const_iterator box_iterator = boxes_.begin();
       box_iterator != boxes_.end(); ++box_iterator) {
    Box* box = *box_iterator;
    do {
      box->InvalidateCrossReferencesOfBoxAndAncestors();
      box = box->GetSplitSibling();
    } while (box != NULL);
  }
}

void LayoutBoxes::InvalidateRenderTreeNodes() {
  for (Boxes::const_iterator box_iterator = boxes_.begin();
       box_iterator != boxes_.end(); ++box_iterator) {
    Box* box = *box_iterator;
    do {
      box->InvalidateRenderTreeNodesOfBoxAndAncestors();
      box = box->GetSplitSibling();
    } while (box != NULL);
  }
}

math::RectF LayoutBoxes::GetBoundingBorderRectangle() const {
  // In the CSSOM View extensions to the HTMLElement interface, at
  // https://www.w3.org/TR/2013/WD-cssom-view-20131217/#extensions-to-the-htmlelement-interface,
  // the standard mentions the 'first CSS layout box associated with the
  // element' and links to a definition 'The term CSS layout box refers to the
  // same term in CSS', which is followed by a note 'ISSUE 2' that mentions 'The
  // terms CSS layout box and SVG layout box are not currently defined by CSS or
  // SVG', at https://www.w3.org/TR/2013/WD-cssom-view-20131217/#css-layout-box.
  // This function calculates the bounding box of the border boxes of the layout
  // boxes, mirroring behavior of most other browsers for the 'first CSS layout
  // box associated with the element'.
  RectLayoutUnit bounding_rectangle;

  for (Boxes::const_iterator box_iterator = boxes_.begin();
       box_iterator != boxes_.end(); ++box_iterator) {
    Box* box = *box_iterator;
    do {
      bounding_rectangle.Union(box->GetBorderBox(false /*stop_at_transform*/));
      box = box->GetSplitSibling();
    } while (box != NULL);
  }

  return math::RectF(bounding_rectangle.x().toFloat(),
                     bounding_rectangle.y().toFloat(),
                     bounding_rectangle.width().toFloat(),
                     bounding_rectangle.height().toFloat());
}

}  // namespace layout
}  // namespace cobalt
