// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/dom/IntersectionObservation.h"

#include "core/dom/ElementRareData.h"
#include "core/dom/IntersectionObserver.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/layout/LayoutBox.h"
#include "core/layout/LayoutView.h"
#include "core/paint/PaintLayer.h"

namespace blink {

IntersectionObservation::IntersectionObservation(IntersectionObserver& observer,
                                                 Element& target,
                                                 bool shouldReportRootBounds)
    : m_observer(observer),
      m_target(&target),
      m_shouldReportRootBounds(shouldReportRootBounds),
      m_lastThresholdIndex(0) {}

void IntersectionObservation::applyRootMargin(LayoutRect& rect) const {
  if (m_shouldReportRootBounds)
    m_observer->applyRootMargin(rect);
}

void IntersectionObservation::initializeGeometry(
    IntersectionGeometry& geometry) const {
  initializeTargetRect(geometry.targetRect);
  geometry.intersectionRect = geometry.targetRect;
  initializeRootRect(geometry.rootRect);
  geometry.doesIntersect = true;
}

void IntersectionObservation::initializeTargetRect(LayoutRect& rect) const {
  DCHECK(m_target);
  LayoutObject* targetLayoutObject = target()->layoutObject();
  DCHECK(targetLayoutObject && targetLayoutObject->isBoxModelObject());
  rect = LayoutRect(
      toLayoutBoxModelObject(targetLayoutObject)->borderBoundingBox());
}

void IntersectionObservation::initializeRootRect(LayoutRect& rect) const {
  LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
  if (rootLayoutObject->isLayoutView())
    rect = LayoutRect(
        toLayoutView(rootLayoutObject)->frameView()->visibleContentRect());
  else if (rootLayoutObject->isBox() && rootLayoutObject->hasOverflowClip())
    rect = LayoutRect(toLayoutBox(rootLayoutObject)->contentBoxRect());
  else
    rect = LayoutRect(
        toLayoutBoxModelObject(rootLayoutObject)->borderBoundingBox());
  applyRootMargin(rect);
}

void IntersectionObservation::clipToRoot(IntersectionGeometry& geometry) const {
  // Map and clip rect into root element coordinates.
  // TODO(szager): the writing mode flipping needs a test.
  DCHECK(m_target);
  LayoutBox* rootLayoutObject = toLayoutBox(m_observer->rootLayoutObject());
  LayoutObject* targetLayoutObject = target()->layoutObject();

  geometry.doesIntersect = targetLayoutObject->mapToVisualRectInAncestorSpace(
      rootLayoutObject, geometry.intersectionRect, EdgeInclusive);
  if (rootLayoutObject->hasOverflowClip())
    geometry.intersectionRect.move(-rootLayoutObject->scrolledContentOffset());

  if (!geometry.doesIntersect)
    return;
  LayoutRect rootClipRect(geometry.rootRect);
  rootLayoutObject->flipForWritingMode(rootClipRect);
  geometry.doesIntersect &=
      geometry.intersectionRect.inclusiveIntersect(rootClipRect);
}

static void mapRectUpToDocument(LayoutRect& rect,
                                const LayoutObject& layoutObject,
                                const Document& document) {
  FloatQuad mappedQuad = layoutObject.localToAbsoluteQuad(
      FloatQuad(FloatRect(rect)), UseTransforms | ApplyContainerFlip);
  rect = LayoutRect(mappedQuad.boundingBox());
}

static void mapRectDownToDocument(LayoutRect& rect,
                                  LayoutBoxModelObject& layoutObject,
                                  const Document& document) {
  FloatQuad mappedQuad = document.layoutView()->ancestorToLocalQuad(
      &layoutObject, FloatQuad(FloatRect(rect)),
      UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries);
  rect = LayoutRect(mappedQuad.boundingBox());
}

void IntersectionObservation::mapTargetRectToTargetFrameCoordinates(
    LayoutRect& rect) const {
  LayoutObject& targetLayoutObject = *target()->layoutObject();
  Document& targetDocument = target()->document();
  LayoutSize scrollPosition = LayoutSize(targetDocument.view()->scrollOffset());
  mapRectUpToDocument(rect, targetLayoutObject, targetDocument);
  rect.move(-scrollPosition);
}

void IntersectionObservation::mapRootRectToRootFrameCoordinates(
    LayoutRect& rect) const {
  LayoutObject& rootLayoutObject = *m_observer->rootLayoutObject();
  Document& rootDocument = rootLayoutObject.document();
  LayoutSize scrollPosition = LayoutSize(rootDocument.view()->scrollOffset());
  mapRectUpToDocument(rect, rootLayoutObject, rootLayoutObject.document());
  rect.move(-scrollPosition);
}

void IntersectionObservation::mapRootRectToTargetFrameCoordinates(
    LayoutRect& rect) const {
  LayoutObject& rootLayoutObject = *m_observer->rootLayoutObject();
  Document& targetDocument = target()->document();
  LayoutSize scrollPosition = LayoutSize(targetDocument.view()->scrollOffset());

  if (&targetDocument == &rootLayoutObject.document())
    mapRectUpToDocument(rect, rootLayoutObject, targetDocument);
  else
    mapRectDownToDocument(rect, toLayoutBoxModelObject(rootLayoutObject),
                          targetDocument);

  rect.move(-scrollPosition);
}

static bool isContainingBlockChainDescendant(LayoutObject* descendant,
                                             LayoutObject* ancestor) {
  LocalFrame* ancestorFrame = ancestor->document().frame();
  LocalFrame* descendantFrame = descendant->document().frame();

  if (ancestor->isLayoutView())
    return descendantFrame && descendantFrame->tree().top() == ancestorFrame;

  if (ancestorFrame != descendantFrame)
    return false;

  while (descendant && descendant != ancestor)
    descendant = descendant->containingBlock();
  return descendant;
}

bool IntersectionObservation::computeGeometry(
    IntersectionGeometry& geometry) const {
  // In the first few lines here, before initializeGeometry is called, "return
  // true" effectively means "if the previous observed state was that root and
  // target were intersecting, then generate a notification indicating that they
  // are no longer intersecting."  This happens, for example, when root or
  // target is removed from the DOM tree and not reinserted before the next
  // frame is generated, or display:none is set on the root or target.
  Element* targetElement = target();
  if (!targetElement)
    return false;
  if (!targetElement->isConnected())
    return true;
  DCHECK(m_observer);
  Element* rootElement = m_observer->root();
  if (rootElement && !rootElement->isConnected())
    return true;

  LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
  if (!rootLayoutObject || !rootLayoutObject->isBoxModelObject())
    return true;
  // TODO(szager): Support SVG
  LayoutObject* targetLayoutObject = targetElement->layoutObject();
  if (!targetLayoutObject)
    return true;
  if (!targetLayoutObject->isBoxModelObject() && !targetLayoutObject->isText())
    return true;
  if (!isContainingBlockChainDescendant(targetLayoutObject, rootLayoutObject))
    return true;

  initializeGeometry(geometry);

  clipToRoot(geometry);

  mapTargetRectToTargetFrameCoordinates(geometry.targetRect);

  if (geometry.doesIntersect)
    mapRootRectToTargetFrameCoordinates(geometry.intersectionRect);
  else
    geometry.intersectionRect = LayoutRect();

  // Small optimization: if we're not going to report root bounds, don't bother
  // transforming them to the frame.
  if (m_shouldReportRootBounds)
    mapRootRectToRootFrameCoordinates(geometry.rootRect);

  return true;
}

void IntersectionObservation::computeIntersectionObservations(
    DOMHighResTimeStamp timestamp) {
  IntersectionGeometry geometry;
  if (!computeGeometry(geometry))
    return;

  // Some corner cases for threshold index:
  //   - If target rect is zero area, because it has zero width and/or zero
  //     height,
  //     only two states are recognized:
  //     - 0 means not intersecting.
  //     - 1 means intersecting.
  //     No other threshold crossings are possible.
  //   - Otherwise:
  //     - If root and target do not intersect, the threshold index is 0.
  //     - If root and target intersect but the intersection has zero-area
  //       (i.e., they have a coincident edge or corner), we consider the
  //       intersection to have "crossed" a zero threshold, but not crossed
  //       any non-zero threshold.
  unsigned newThresholdIndex;
  float newVisibleRatio = 0;
  if (geometry.targetRect.isEmpty()) {
    newThresholdIndex = geometry.doesIntersect ? 1 : 0;
  } else if (!geometry.doesIntersect) {
    newThresholdIndex = 0;
  } else {
    float intersectionArea =
        geometry.intersectionRect.size().width().toFloat() *
        geometry.intersectionRect.size().height().toFloat();
    float targetArea = geometry.targetRect.size().width().toFloat() *
                       geometry.targetRect.size().height().toFloat();
    newVisibleRatio = intersectionArea / targetArea;
    newThresholdIndex = observer().firstThresholdGreaterThan(newVisibleRatio);
  }
  if (m_lastThresholdIndex != newThresholdIndex) {
    IntRect snappedRootBounds = pixelSnappedIntRect(geometry.rootRect);
    IntRect* rootBoundsPointer =
        m_shouldReportRootBounds ? &snappedRootBounds : nullptr;
    IntersectionObserverEntry* newEntry = new IntersectionObserverEntry(
        timestamp, newVisibleRatio, pixelSnappedIntRect(geometry.targetRect),
        rootBoundsPointer, pixelSnappedIntRect(geometry.intersectionRect),
        target());
    observer().enqueueIntersectionObserverEntry(*newEntry);
    setLastThresholdIndex(newThresholdIndex);
  }
}

void IntersectionObservation::disconnect() {
  IntersectionObserver* observer = m_observer;
  clearRootAndRemoveFromTarget();
  observer->removeObservation(*this);
}

void IntersectionObservation::clearRootAndRemoveFromTarget() {
  if (m_target)
    target()->ensureIntersectionObserverData().removeObservation(observer());
  m_observer.clear();
}

DEFINE_TRACE(IntersectionObservation) {
  visitor->trace(m_observer);
  visitor->trace(m_target);
}

}  // namespace blink
