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

#include <algorithm>
#include <vector>

#include "base/trace_event/trace_event.h"
#include "cobalt/cssom/computed_style_utils.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/box.h"
#include "cobalt/layout/container_box.h"
#include "cobalt/layout/intersection_observer_root.h"
#include "cobalt/layout/used_style.h"

namespace cobalt {
namespace layout {

void IntersectionObserverTarget::UpdateIntersectionObservationsForTarget(
    ContainerBox* target_box) {
  TRACE_EVENT0(
      "cobalt::layout",
      "IntersectionObserverTarget::UpdateIntersectionObservationsForTarget()");
  // Walk up the containing block chain looking for the box referencing the
  // IntersectionObserverRoot corresponding to this IntersectionObserverTarget.
  // Skip further processing for the target if it is not a descendant of the
  // root in the containing block chain.
  const ContainerBox* root_box = target_box->GetContainingBlock();
  while (!root_box->ContainsIntersectionObserverRoot(
      intersection_observer_root_)) {
    if (!root_box->parent()) {
      return;
    }
    root_box = root_box->GetContainingBlock();
  }

  // Let targetRect be target's bounding border box.
  RectLayoutUnit target_transformed_border_box(
      target_box->GetTransformedBorderBoxFromRoot());
  math::RectF target_rect =
      math::RectF(target_transformed_border_box.x().toFloat(),
                  target_transformed_border_box.y().toFloat(),
                  target_transformed_border_box.width().toFloat(),
                  target_transformed_border_box.height().toFloat());

  // Let intersectionRect be the result of running the compute the intersection
  // algorithm on target.
  math::RectF root_bounds = GetRootBounds(
      root_box, intersection_observer_root_->root_margin_property_value());
  math::RectF intersection_rect = ComputeIntersectionBetweenTargetAndRoot(
      root_box, root_bounds, target_rect, target_box);

  // Let targetArea be targetRect's area.
  float target_area = target_rect.size().GetArea();

  // Let intersectionArea be intersectionRect's area.
  float intersection_area = intersection_rect.size().GetArea();

  // If targetArea is non-zero, let intersectionRatio be intersectionArea
  // divided by targetArea. Otherwise, let intersectionRatio be 1 if
  // targetRect and rootBounds are edge-adjacent (in the case that targetRect or
  // rootbounds have zero area), and 0 otherwise.
  float intersection_ratio =
      (intersection_rect.width() != 0 || intersection_rect.height() != 0)
          ? 1.0f
          : 0.0f;
  if (target_area != 0) {
    intersection_ratio = intersection_area / target_area;
  }

  // Let thresholdIndex be the index of the first entry in observer.thresholds
  // whose value is greater than intersectionRatio, or the length of
  // observer.thresholds if intersectionRatio is greater than or equal to the
  // last entry in observer.thresholds.
  const std::vector<double>& thresholds =
      intersection_observer_root_->thresholds_vector();
  size_t threshold_index;
  for (threshold_index = 0; threshold_index < thresholds.size();
       ++threshold_index) {
    if (thresholds.at(threshold_index) > intersection_ratio) {
      break;
    }
  }

  // Set isIntersecting to true if |threshold_index| > 0, and false otherwise.
  bool is_intersecting = threshold_index > 0;

  // If thresholdIndex does not equal previousThresholdIndex or if
  // isIntersecting does not equal previousIsIntersecting, queue an
  // IntersectionObserverEntry, passing in observer, time, rootBounds,
  //         boundingClientRect, intersectionRect, isIntersecting, and target.
  if (static_cast<int32>(threshold_index) != previous_threshold_index_ ||
      is_intersecting != previous_is_intersecting_) {
    on_intersection_callback_.Run(root_bounds, target_rect, intersection_rect,
                                  is_intersecting, intersection_ratio);
  }

  // Update the previousThresholdIndex and previousIsIntersecting properties.
  previous_threshold_index_ = static_cast<int32>(threshold_index);
  previous_is_intersecting_ = is_intersecting;
}

bool IntersectionObserverTarget::IsInContainingBlockChain(
    const ContainerBox* potential_containing_block,
    const ContainerBox* target_box) {
  const ContainerBox* containing_block = target_box->GetContainingBlock();
  while (containing_block != potential_containing_block) {
    if (!containing_block->parent()) {
      return false;
    }
    containing_block = containing_block->GetContainingBlock();
  }
  return true;
}

math::RectF IntersectionObserverTarget::GetRootBounds(
    const ContainerBox* root_box,
    scoped_refptr<cssom::PropertyListValue> root_margin_property_value) {
  math::RectF root_bounds_without_margins;
  if (IsOverflowCropped(root_box->computed_style())) {
    // If the intersection root has an overflow clip, it's the element's content
    // area.
    Vector2dLayoutUnit content_edge_offset =
        root_box->GetContentBoxOffsetFromRoot(false /*transform_forms_root*/);
    root_bounds_without_margins = math::RectF(
        content_edge_offset.x().toFloat(), content_edge_offset.y().toFloat(),
        root_box->width().toFloat(), root_box->height().toFloat());
  } else {
    // Otherwise, it's the result of running the getBoundingClientRect()
    // algorithm on the intersection root.
    RectLayoutUnit root_transformed_border_box(
        root_box->GetTransformedBorderBoxFromRoot());
    root_bounds_without_margins =
        math::RectF(root_transformed_border_box.x().toFloat(),
                    root_transformed_border_box.y().toFloat(),
                    root_transformed_border_box.width().toFloat(),
                    root_transformed_border_box.height().toFloat());
  }
  int32 top_margin = GetUsedLengthOfRootMarginPropertyValue(
      root_margin_property_value->value()[0],
      LayoutUnit(root_bounds_without_margins.height()));
  int32 right_margin = GetUsedLengthOfRootMarginPropertyValue(
      root_margin_property_value->value()[1],
      LayoutUnit(root_bounds_without_margins.width()));
  int32 bottom_margin = GetUsedLengthOfRootMarginPropertyValue(
      root_margin_property_value->value()[2],
      LayoutUnit(root_bounds_without_margins.height()));
  int32 left_margin = GetUsedLengthOfRootMarginPropertyValue(
      root_margin_property_value->value()[3],
      LayoutUnit(root_bounds_without_margins.width()));

  // Remember to grow or shrink the root intersection rectangle bounds based
  // on the root margin property.
  math::RectF root_bounds = math::RectF(
      root_bounds_without_margins.x() - left_margin,
      root_bounds_without_margins.y() - top_margin,
      root_bounds_without_margins.width() + left_margin + right_margin,
      root_bounds_without_margins.height() + top_margin + bottom_margin);
  return root_bounds;
}

int32 IntersectionObserverTarget::GetUsedLengthOfRootMarginPropertyValue(
    const scoped_refptr<cssom::PropertyValue>& length_property_value,
    LayoutUnit percentage_base) {
  UsedLengthValueProvider used_length_provider(percentage_base);
  length_property_value->Accept(&used_length_provider);
  // Not explicitly stated in web spec, but has been observed that Chrome
  // truncates root margin decimal values.
  return static_cast<int32>(
      used_length_provider.used_length().value_or(LayoutUnit(0.0f)).toFloat());
}

math::RectF IntersectionObserverTarget::ComputeIntersectionBetweenTargetAndRoot(
    const ContainerBox* root_box, const math::RectF& root_bounds,
    const math::RectF& target_rect, const ContainerBox* target_box) {
  // Let intersectionRect be target's bounding border box.
  math::RectF intersection_rect = target_rect;

  // Let container be the containing block of the target.
  math::Vector2dF total_offset_from_containing_block =
      target_box->GetBorderBoxOffsetFromContainingBlock();
  const ContainerBox* prev_container = target_box;
  const ContainerBox* container = prev_container->GetContainingBlock();

  // While container is not the intersection root:
  while (container != root_box) {
    // Map intersectionRect to the coordinate space of container.
    intersection_rect.set_x(total_offset_from_containing_block.x());
    intersection_rect.set_y(total_offset_from_containing_block.y());

    // If container has overflow clipping or a css clip-path property, update
    // intersectionRect by applying container's clip. (Note: The containing
    // block of an element with 'position: absolute' is formed by the padding
    // edge of the ancestor. https://www.w3.org/TR/CSS2/visudet.html)
    if (IsOverflowCropped(container->computed_style())) {
      Vector2dLayoutUnit container_clip_dimensions =
          prev_container->computed_style()->position() ==
                  cssom::KeywordValue::GetAbsolute()
              ? Vector2dLayoutUnit(container->GetPaddingBoxWidth(),
                                   container->GetPaddingBoxHeight())
              : Vector2dLayoutUnit(container->width(), container->height());
      math::RectF container_clip(0.0f, 0.0f,
                                 container_clip_dimensions.x().toFloat(),
                                 container_clip_dimensions.y().toFloat());
      intersection_rect =
          IntersectIntersectionObserverRects(intersection_rect, container_clip);
    }

    // If container is the root element of a nested browsing context, update
    // container to be the browsing context container of container, and update
    // intersectionRect by clipping to the viewport of the nested browsing
    // context. Otherwise, update container to be the containing block of
    // container. (Note: The containing block of an element with 'position:
    // absolute' is formed by the padding edge of the ancestor.
    // https://www.w3.org/TR/CSS2/visudet.html)
    math::Vector2dF next_offset_from_containing_block =
        prev_container->computed_style()->position() ==
                cssom::KeywordValue::GetAbsolute()
            ? container->GetPaddingBoxOffsetFromContainingBlock()
            : container->GetContentBoxOffsetFromContainingBlockContentBox(
                  container->GetContainingBlock());
    total_offset_from_containing_block += next_offset_from_containing_block;

    prev_container = container;
    container = prev_container->GetContainingBlock();
  }

  // Map intersectionRect to the coordinate space of the viewport of the
  // Document containing the target.
  // (Note: The containing block of an element with 'position: absolute'
  // is formed by the padding edge of the ancestor.
  // https://www.w3.org/TR/CSS2/visudet.html)
  math::Vector2dF containing_block_offset_from_origin =
      prev_container->computed_style()->position() ==
                  cssom::KeywordValue::GetAbsolute() &&
              !IsOverflowCropped(container->computed_style())
          ? container->GetPaddingBoxOffsetFromRoot(
                false /*transform_forms_root*/)
          : container->GetContentBoxOffsetFromRoot(
                false /*transform_forms_root*/);

  intersection_rect.set_x(total_offset_from_containing_block.x() +
                          containing_block_offset_from_origin.x());
  intersection_rect.set_y(total_offset_from_containing_block.y() +
                          containing_block_offset_from_origin.y());

  // Update intersectionRect by intersecting it with the root intersection
  // rectangle, which is already in this coordinate space.
  intersection_rect =
      IntersectIntersectionObserverRects(intersection_rect, root_bounds);
  return intersection_rect;
}

math::RectF IntersectionObserverTarget::IntersectIntersectionObserverRects(
    const math::RectF& a, const math::RectF& b) {
  float rx = std::max(a.x(), b.x());
  float ry = std::max(a.y(), b.y());
  float rr = std::min(a.right(), b.right());
  float rb = std::min(a.bottom(), b.bottom());

  if (rx > rr || ry > rb) {
    return math::RectF(0.0f, 0.0f, 0.0f, 0.0f);
  }

  return math::RectF(rx, ry, rr - rx, rb - ry);
}

}  // namespace layout
}  // namespace cobalt
