/*
 * Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "third_party/blink/renderer/core/layout/hit_test_result.h"

#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
#include "third_party/blink/renderer/core/html/html_area_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/html_map_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/scroll/scrollbar.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"

namespace blink {

using namespace html_names;

HitTestResult::HitTestResult()
    : hit_test_request_(HitTestRequest::kReadOnly | HitTestRequest::kActive),
      cacheable_(true),
      is_over_embedded_content_view_(false) {}

HitTestResult::HitTestResult(const HitTestRequest& other_request,
                             const HitTestLocation& location)
    : hit_test_request_(other_request),
      cacheable_(true),
      point_in_inner_node_frame_(location.Point()),
      is_over_embedded_content_view_(false) {}

HitTestResult::HitTestResult(const HitTestResult& other)
    : hit_test_request_(other.hit_test_request_),
      cacheable_(other.cacheable_),
      inner_node_(other.InnerNode()),
      inner_possibly_pseudo_node_(other.inner_possibly_pseudo_node_),
      point_in_inner_node_frame_(other.point_in_inner_node_frame_),
      local_point_(other.LocalPoint()),
      inner_url_element_(other.URLElement()),
      scrollbar_(other.GetScrollbar()),
      is_over_embedded_content_view_(other.IsOverEmbeddedContentView()),
      canvas_region_id_(other.CanvasRegionId()) {
  // Only copy the NodeSet in case of list hit test.
  list_based_test_result_ =
      other.list_based_test_result_
          ? MakeGarbageCollected<NodeSet>(*other.list_based_test_result_)
          : nullptr;
}

HitTestResult::~HitTestResult() = default;

HitTestResult& HitTestResult::operator=(const HitTestResult& other) {
  hit_test_request_ = other.hit_test_request_;
  PopulateFromCachedResult(other);

  return *this;
}

bool HitTestResult::EqualForCacheability(const HitTestResult& other) const {
  return hit_test_request_.EqualForCacheability(other.hit_test_request_) &&
         inner_node_ == other.InnerNode() &&
         inner_possibly_pseudo_node_ == other.InnerPossiblyPseudoNode() &&
         point_in_inner_node_frame_ == other.point_in_inner_node_frame_ &&
         local_point_ == other.LocalPoint() &&
         inner_url_element_ == other.URLElement() &&
         scrollbar_ == other.GetScrollbar() &&
         is_over_embedded_content_view_ == other.IsOverEmbeddedContentView();
}

void HitTestResult::CacheValues(const HitTestResult& other) {
  hit_test_request_ =
      other.hit_test_request_.GetType() & ~HitTestRequest::kAvoidCache;
}

void HitTestResult::PopulateFromCachedResult(const HitTestResult& other) {
  inner_node_ = other.InnerNode();
  inner_possibly_pseudo_node_ = other.InnerPossiblyPseudoNode();
  point_in_inner_node_frame_ = other.point_in_inner_node_frame_;
  local_point_ = other.LocalPoint();
  inner_url_element_ = other.URLElement();
  scrollbar_ = other.GetScrollbar();
  is_over_embedded_content_view_ = other.IsOverEmbeddedContentView();
  cacheable_ = other.cacheable_;
  canvas_region_id_ = other.CanvasRegionId();

  // Only copy the NodeSet in case of list hit test.
  list_based_test_result_ =
      other.list_based_test_result_
          ? MakeGarbageCollected<NodeSet>(*other.list_based_test_result_)
          : nullptr;
}

void HitTestResult::Trace(blink::Visitor* visitor) {
  visitor->Trace(inner_node_);
  visitor->Trace(inner_possibly_pseudo_node_);
  visitor->Trace(inner_url_element_);
  visitor->Trace(scrollbar_);
  visitor->Trace(list_based_test_result_);
}

PositionWithAffinity HitTestResult::GetPosition() const {
  if (!inner_possibly_pseudo_node_)
    return PositionWithAffinity();
  LayoutObject* layout_object = GetLayoutObject();
  if (!layout_object)
    return PositionWithAffinity();
  if (inner_possibly_pseudo_node_->IsPseudoElement() &&
      inner_possibly_pseudo_node_->GetPseudoId() == kPseudoIdBefore) {
    return PositionWithAffinity(MostForwardCaretPosition(
        Position(inner_node_, PositionAnchorType::kBeforeChildren)));
  }
  return layout_object->PositionForPoint(LocalPoint());
}

LayoutObject* HitTestResult::GetLayoutObject() const {
  return inner_node_ ? inner_node_->GetLayoutObject() : nullptr;
}

void HitTestResult::SetToShadowHostIfInRestrictedShadowRoot() {
  Node* node = InnerNode();
  if (!node)
    return;

  ShadowRoot* containing_shadow_root = node->ContainingShadowRoot();
  Element* shadow_host = nullptr;

  // Consider a closed shadow tree of SVG's <use> element as a special
  // case so that a toolip title in the shadow tree works.
  while (containing_shadow_root &&
         (containing_shadow_root->IsUserAgent() ||
          IsSVGUseElement(containing_shadow_root->host()))) {
    shadow_host = &containing_shadow_root->host();
    containing_shadow_root = shadow_host->ContainingShadowRoot();
    SetInnerNode(node->OwnerShadowHost());
  }

  if (shadow_host)
    SetInnerNode(shadow_host);
}

HTMLAreaElement* HitTestResult::ImageAreaForImage() const {
  DCHECK(inner_node_);
  HTMLImageElement* image_element = ToHTMLImageElementOrNull(inner_node_);
  if (!image_element && inner_node_->IsInShadowTree()) {
    if (inner_node_->ContainingShadowRoot()->IsUserAgent()) {
      image_element = ToHTMLImageElementOrNull(inner_node_->OwnerShadowHost());
    }
  }

  if (!image_element || !image_element->GetLayoutObject() ||
      !image_element->GetLayoutObject()->IsBox())
    return nullptr;

  HTMLMapElement* map = image_element->GetTreeScope().GetImageMap(
      image_element->FastGetAttribute(kUsemapAttr));
  if (!map)
    return nullptr;

  return map->AreaForPoint(LocalPoint(), image_element->GetLayoutObject());
}

void HitTestResult::SetInnerNode(Node* n) {
  inner_possibly_pseudo_node_ = n;
  if (!n) {
    inner_node_ = n;
    return;
  }
  if (n->IsPseudoElement())
    n = ToPseudoElement(n)->InnerNodeForHitTesting();
  inner_node_ = n;
  if (HTMLAreaElement* area = ImageAreaForImage()) {
    inner_node_ = area;
    inner_possibly_pseudo_node_ = area;
  }
}

void HitTestResult::SetURLElement(Element* n) {
  inner_url_element_ = n;
}

void HitTestResult::SetScrollbar(Scrollbar* s) {
  scrollbar_ = s;
}

LocalFrame* HitTestResult::InnerNodeFrame() const {
  if (inner_node_)
    return inner_node_->GetDocument().GetFrame();
  return nullptr;
}

bool HitTestResult::IsSelected(const HitTestLocation& location) const {
  if (!inner_node_)
    return false;

  if (LocalFrame* frame = inner_node_->GetDocument().GetFrame())
    return frame->Selection().Contains(location.Point());
  return false;
}

String HitTestResult::Title(TextDirection& dir) const {
  dir = TextDirection::kLtr;
  // Find the title in the nearest enclosing DOM node.
  // For <area> tags in image maps, walk the tree for the <area>, not the <img>
  // using it.
  if (inner_node_.Get())
    inner_node_->UpdateDistributionForFlatTreeTraversal();
  for (Node* title_node = inner_node_.Get(); title_node;
       title_node = FlatTreeTraversal::Parent(*title_node)) {
    if (title_node->IsElementNode()) {
      String title = ToElement(title_node)->title();
      if (!title.IsNull()) {
        if (LayoutObject* layout_object = title_node->GetLayoutObject())
          dir = layout_object->StyleRef().Direction();
        return title;
      }
    }
  }
  return String();
}

const AtomicString& HitTestResult::AltDisplayString() const {
  Node* inner_node_or_image_map_image = InnerNodeOrImageMapImage();
  if (!inner_node_or_image_map_image)
    return g_null_atom;

  if (auto* image = ToHTMLImageElementOrNull(*inner_node_or_image_map_image))
    return image->getAttribute(kAltAttr);

  if (auto* input = ToHTMLInputElementOrNull(*inner_node_or_image_map_image))
    return input->Alt();

  return g_null_atom;
}

Image* HitTestResult::GetImage() const {
  Node* inner_node_or_image_map_image = InnerNodeOrImageMapImage();
  if (!inner_node_or_image_map_image)
    return nullptr;

  LayoutObject* layout_object =
      inner_node_or_image_map_image->GetLayoutObject();
  if (layout_object && layout_object->IsImage()) {
    LayoutImage* image = ToLayoutImage(layout_object);
    if (image->CachedImage() && !image->CachedImage()->ErrorOccurred())
      return image->CachedImage()->GetImage();
  }

  return nullptr;
}

IntRect HitTestResult::ImageRect() const {
  if (!GetImage())
    return IntRect();
  return InnerNodeOrImageMapImage()
      ->GetLayoutBox()
      ->AbsoluteContentQuad()
      .EnclosingBoundingBox();
}

KURL HitTestResult::AbsoluteImageURL() const {
  Node* inner_node_or_image_map_image = InnerNodeOrImageMapImage();
  if (!inner_node_or_image_map_image)
    return KURL();

  AtomicString url_string;
  // Always return a url for image elements and input elements with type=image,
  // even if they don't have a LayoutImage (e.g. because the image didn't load
  // and we are using an alt container). For other elements we don't create alt
  // containers so ensure they contain a loaded image.
  if (IsHTMLImageElement(*inner_node_or_image_map_image) ||
      (IsHTMLInputElement(*inner_node_or_image_map_image) &&
       ToHTMLInputElement(inner_node_or_image_map_image)->type() ==
           input_type_names::kImage))
    url_string = ToElement(*inner_node_or_image_map_image).ImageSourceURL();
  else if ((inner_node_or_image_map_image->GetLayoutObject() &&
            inner_node_or_image_map_image->GetLayoutObject()->IsImage()) &&
           (IsHTMLEmbedElement(*inner_node_or_image_map_image) ||
            IsHTMLObjectElement(*inner_node_or_image_map_image) ||
            IsSVGImageElement(*inner_node_or_image_map_image)))
    url_string = ToElement(*inner_node_or_image_map_image).ImageSourceURL();
  if (url_string.IsEmpty())
    return KURL();

  return inner_node_or_image_map_image->GetDocument().CompleteURL(
      StripLeadingAndTrailingHTMLSpaces(url_string));
}

KURL HitTestResult::AbsoluteMediaURL() const {
  if (HTMLMediaElement* media_elt = MediaElement())
    return media_elt->currentSrc();
  return KURL();
}

MediaStreamDescriptor* HitTestResult::GetMediaStreamDescriptor() const {
  if (HTMLMediaElement* media_elt = MediaElement())
    return media_elt->GetSrcObject();
  return nullptr;
}

HTMLMediaElement* HitTestResult::MediaElement() const {
  if (!inner_node_)
    return nullptr;

  if (!(inner_node_->GetLayoutObject() &&
        inner_node_->GetLayoutObject()->IsMedia()))
    return nullptr;

  if (IsHTMLMediaElement(*inner_node_))
    return ToHTMLMediaElement(inner_node_);
  return nullptr;
}

KURL HitTestResult::AbsoluteLinkURL() const {
  if (!inner_url_element_)
    return KURL();
  return inner_url_element_->HrefURL();
}

bool HitTestResult::IsLiveLink() const {
  return inner_url_element_ && inner_url_element_->IsLiveLink();
}

bool HitTestResult::IsOverLink() const {
  return inner_url_element_ && inner_url_element_->IsLink();
}

String HitTestResult::TextContent() const {
  if (!inner_url_element_)
    return String();
  return inner_url_element_->textContent();
}

// FIXME: This function needs a better name and may belong in a different class.
// It's not really isContentEditable(); it's more like needsEditingContextMenu.
// In many ways, this function would make more sense in the ContextMenu class,
// except that WebElementDictionary hooks into it. Anyway, we should architect
// this better.
bool HitTestResult::IsContentEditable() const {
  if (!inner_node_)
    return false;

  if (auto* textarea = ToHTMLTextAreaElementOrNull(*inner_node_))
    return !textarea->IsDisabledOrReadOnly();

  if (auto* input = ToHTMLInputElementOrNull(*inner_node_))
    return !input->IsDisabledOrReadOnly() && input->IsTextField();

  return HasEditableStyle(*inner_node_);
}

ListBasedHitTestBehavior HitTestResult::AddNodeToListBasedTestResult(
    Node* node,
    const HitTestLocation& location,
    const LayoutRect& rect) {
  // If not a list-based test, stop testing because the hit has been found.
  if (!GetHitTestRequest().ListBased())
    return kStopHitTesting;

  if (!node)
    return kContinueHitTesting;

  MutableListBasedTestResult().insert(node);

  if (GetHitTestRequest().PenetratingList())
    return kContinueHitTesting;

  return rect.Contains(location.BoundingBox()) ? kStopHitTesting
                                               : kContinueHitTesting;
}

ListBasedHitTestBehavior HitTestResult::AddNodeToListBasedTestResult(
    Node* node,
    const HitTestLocation& location,
    const Region& region) {
  // If not a list-based test, stop testing because the hit has been found.
  if (!GetHitTestRequest().ListBased())
    return kStopHitTesting;

  if (!node)
    return kContinueHitTesting;

  MutableListBasedTestResult().insert(node);

  if (GetHitTestRequest().PenetratingList())
    return kContinueHitTesting;

  return region.Contains(location.EnclosingIntRect()) ? kStopHitTesting
                                                      : kContinueHitTesting;
}

void HitTestResult::Append(const HitTestResult& other) {
  DCHECK(GetHitTestRequest().ListBased());

  if (!scrollbar_ && other.GetScrollbar()) {
    SetScrollbar(other.GetScrollbar());
  }

  if (!inner_node_ && other.InnerNode()) {
    inner_node_ = other.InnerNode();
    inner_possibly_pseudo_node_ = other.InnerPossiblyPseudoNode();
    local_point_ = other.LocalPoint();
    point_in_inner_node_frame_ = other.point_in_inner_node_frame_;
    inner_url_element_ = other.URLElement();
    is_over_embedded_content_view_ = other.IsOverEmbeddedContentView();
    canvas_region_id_ = other.CanvasRegionId();
  }

  if (other.list_based_test_result_) {
    NodeSet& set = MutableListBasedTestResult();
    for (NodeSet::const_iterator it = other.list_based_test_result_->begin(),
                                 last = other.list_based_test_result_->end();
         it != last; ++it)
      set.insert(it->Get());
  }
}

const HitTestResult::NodeSet& HitTestResult::ListBasedTestResult() const {
  if (!list_based_test_result_)
    list_based_test_result_ = MakeGarbageCollected<NodeSet>();
  return *list_based_test_result_;
}

HitTestResult::NodeSet& HitTestResult::MutableListBasedTestResult() {
  if (!list_based_test_result_)
    list_based_test_result_ = MakeGarbageCollected<NodeSet>();
  return *list_based_test_result_;
}

HitTestLocation HitTestResult::ResolveRectBasedTest(
    Node* resolved_inner_node,
    const LayoutPoint& resolved_point_in_main_frame) {
  point_in_inner_node_frame_ = resolved_point_in_main_frame;
  inner_node_ = nullptr;
  inner_possibly_pseudo_node_ = nullptr;
  list_based_test_result_ = nullptr;

  // Update the HitTestResult as if the supplied node had been hit in normal
  // point-based hit-test.
  // Note that we don't know the local point after a rect-based hit-test, but we
  // never use it so shouldn't bother with the cost of computing it.
  DCHECK(resolved_inner_node);
  if (auto* layout_object = resolved_inner_node->GetLayoutObject())
    layout_object->UpdateHitTestResult(*this, LayoutPoint());

  return HitTestLocation(resolved_point_in_main_frame);
}

Element* HitTestResult::InnerElement() const {
  if (!inner_node_)
    return nullptr;
  if (inner_node_->IsElementNode())
    return ToElement(inner_node_);
  return FlatTreeTraversal::ParentElement(*inner_node_);
}

Node* HitTestResult::InnerNodeOrImageMapImage() const {
  if (!inner_node_)
    return nullptr;

  HTMLImageElement* image_map_image_element = nullptr;
  if (auto* area = ToHTMLAreaElementOrNull(inner_node_))
    image_map_image_element = area->ImageElement();
  else if (auto* map = ToHTMLMapElementOrNull(inner_node_))
    image_map_image_element = map->ImageElement();

  if (!image_map_image_element)
    return inner_node_.Get();

  return image_map_image_element;
}

}  // namespace blink
