// 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 "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) {
  // 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();

  // Let isIntersecting be true if targetRect and rootBounds intersect or are
  // edge-adjacent, even if the intersection has zero area (because rootBounds
  // or targetRect have zero area); otherwise, let isIntersecting be false.
  bool is_intersecting =
      intersection_rect.width() != 0 || intersection_rect.height() != 0;

  // If targetArea is non-zero, let intersectionRatio be intersectionArea
  // divided by targetArea. Otherwise, let intersectionRatio be 1 if
  // isIntersecting is true, or 0 if isIntersecting is false.
  float intersection_ratio = is_intersecting ? 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;
    }
  }

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