/*
 * 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/page/touch_adjustment.h"

#include "third_party/blink/public/platform/web_screen_info.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/editing_behavior.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"

namespace blink {

namespace touch_adjustment {

const float kZeroTolerance = 1e-6f;
// The maximum adjustment range (diameters) in dip.
constexpr float kMaxAdjustmentSizeDip = 32.f;

// Class for remembering absolute quads of a target node and what node they
// represent.
class SubtargetGeometry {
  DISALLOW_NEW();

 public:
  SubtargetGeometry(Node* node, const FloatQuad& quad)
      : node_(node), quad_(quad) {}
  void Trace(blink::Visitor* visitor) { visitor->Trace(node_); }

  Node* GetNode() const { return node_; }
  FloatQuad Quad() const { return quad_; }
  IntRect BoundingBox() const { return quad_.EnclosingBoundingBox(); }

 private:
  Member<Node> node_;
  FloatQuad quad_;
};

}  // namespace touch_adjustment

}  // namespace blink

WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(
    blink::touch_adjustment::SubtargetGeometry)

namespace blink {

namespace touch_adjustment {

typedef HeapVector<SubtargetGeometry> SubtargetGeometryList;
typedef bool (*NodeFilter)(Node*);
typedef void (*AppendSubtargetsForNode)(Node*, SubtargetGeometryList&);
typedef float (*DistanceFunction)(const IntPoint&,
                                  const IntRect&,
                                  const SubtargetGeometry&);

// Takes non-const Node* because isContentEditable is a non-const function.
bool NodeRespondsToTapGesture(Node* node) {
  if (node->WillRespondToMouseClickEvents() ||
      node->WillRespondToMouseMoveEvents())
    return true;
  if (node->IsElementNode()) {
    Element* element = ToElement(node);
    // Tapping on a text field or other focusable item should trigger
    // adjustment, except that iframe elements are hard-coded to support focus
    // but the effect is often invisible so they should be excluded.
    if (element->IsMouseFocusable() && !IsHTMLIFrameElement(element))
      return true;
    // Accept nodes that has a CSS effect when touched.
    if (element->ChildrenOrSiblingsAffectedByActive() ||
        element->ChildrenOrSiblingsAffectedByHover())
      return true;
  }
  if (const ComputedStyle* computed_style = node->GetComputedStyle()) {
    if (computed_style->AffectedByActive() || computed_style->AffectedByHover())
      return true;
  }
  return false;
}

bool NodeIsZoomTarget(Node* node) {
  if (node->IsTextNode() || node->IsShadowRoot())
    return false;

  DCHECK(node->GetLayoutObject());
  return node->GetLayoutObject()->IsBox();
}

bool ProvidesContextMenuItems(Node* node) {
  // This function tries to match the nodes that receive special context-menu
  // items in ContextMenuController::populate(), and should be kept uptodate
  // with those.
  DCHECK(node->GetLayoutObject() || node->IsShadowRoot());
  if (!node->GetLayoutObject())
    return false;
  node->GetDocument().UpdateStyleAndLayoutTree();
  if (HasEditableStyle(*node))
    return true;
  if (node->IsLink())
    return true;
  if (node->GetLayoutObject()->IsImage())
    return true;
  if (node->GetLayoutObject()->IsMedia())
    return true;
  if (node->GetLayoutObject()->CanBeSelectionLeaf()) {
    // If the context menu gesture will trigger a selection all selectable nodes
    // are valid targets.
    if (node->GetLayoutObject()
            ->GetFrame()
            ->GetEditor()
            .Behavior()
            .ShouldSelectOnContextualMenuClick())
      return true;
    // Only the selected part of the layoutObject is a valid target, but this
    // will be corrected in appendContextSubtargetsForNode.
    if (node->GetLayoutObject()->IsSelected())
      return true;
  }
  return false;
}

static inline void AppendQuadsToSubtargetList(
    Vector<FloatQuad>& quads,
    Node* node,
    SubtargetGeometryList& subtargets) {
  Vector<FloatQuad>::const_iterator it = quads.begin();
  const Vector<FloatQuad>::const_iterator end = quads.end();
  for (; it != end; ++it)
    subtargets.push_back(SubtargetGeometry(node, *it));
}

static inline void AppendBasicSubtargetsForNode(
    Node* node,
    SubtargetGeometryList& subtargets) {
  // Node guaranteed to have layoutObject due to check in node filter.
  DCHECK(node->GetLayoutObject());

  Vector<FloatQuad> quads;
  node->GetLayoutObject()->AbsoluteQuads(quads);

  AppendQuadsToSubtargetList(quads, node, subtargets);
}

static inline void AppendContextSubtargetsForNode(
    Node* node,
    SubtargetGeometryList& subtargets) {
  // This is a variant of appendBasicSubtargetsForNode that adds special
  // subtargets for selected or auto-selectable parts of text nodes.
  DCHECK(node->GetLayoutObject());

  if (!node->IsTextNode())
    return AppendBasicSubtargetsForNode(node, subtargets);

  Text* text_node = ToText(node);
  LayoutText* text_layout_object = text_node->GetLayoutObject();

  if (text_layout_object->GetFrame()
          ->GetEditor()
          .Behavior()
          .ShouldSelectOnContextualMenuClick()) {
    // Make subtargets out of every word.
    String text_value = text_node->data();
    TextBreakIterator* word_iterator =
        WordBreakIterator(text_value, 0, text_value.length());
    int last_offset = word_iterator->first();
    if (last_offset == -1)
      return;
    int offset;
    while ((offset = word_iterator->next()) != -1) {
      if (IsWordTextBreak(word_iterator)) {
        Vector<FloatQuad> quads;
        text_layout_object->AbsoluteQuadsForRange(quads, last_offset, offset);
        AppendQuadsToSubtargetList(quads, text_node, subtargets);
      }
      last_offset = offset;
    }
  } else {
    if (!text_layout_object->IsSelected())
      return AppendBasicSubtargetsForNode(node, subtargets);
    const FrameSelection& frame_selection =
        text_layout_object->GetFrame()->Selection();
    const LayoutTextSelectionStatus& selection_status =
        frame_selection.ComputeLayoutSelectionStatus(*text_layout_object);
    // If selected, make subtargets out of only the selected part of the text.
    Vector<FloatQuad> quads;
    text_layout_object->AbsoluteQuadsForRange(quads, selection_status.start,
                                              selection_status.end);
    AppendQuadsToSubtargetList(quads, text_node, subtargets);
  }
}

static inline Node* ParentShadowHostOrOwner(const Node* node) {
  if (Node* ancestor = node->ParentOrShadowHostNode())
    return ancestor;
  if (auto* document = DynamicTo<Document>(node))
    return document->LocalOwner();
  return nullptr;
}

// Compiles a list of subtargets of all the relevant target nodes.
void CompileSubtargetList(const HeapVector<Member<Node>>& intersected_nodes,
                          SubtargetGeometryList& subtargets,
                          NodeFilter node_filter,
                          AppendSubtargetsForNode append_subtargets_for_node) {
  // Find candidates responding to tap gesture events in O(n) time.
  HeapHashMap<Member<Node>, Member<Node>> responder_map;
  HeapHashSet<Member<Node>> ancestors_to_responders_set;
  HeapVector<Member<Node>> candidates;
  HeapHashSet<Member<Node>> editable_ancestors;

  // A node matching the NodeFilter is called a responder. Candidate nodes must
  // either be a responder or have an ancestor that is a responder.  This
  // iteration tests all ancestors at most once by caching earlier results.
  for (unsigned i = 0; i < intersected_nodes.size(); ++i) {
    Node* node = intersected_nodes[i].Get();
    HeapVector<Member<Node>> visited_nodes;
    Node* responding_node = nullptr;
    for (Node* visited_node = node; visited_node;
         visited_node = visited_node->ParentOrShadowHostNode()) {
      // Check if we already have a result for a common ancestor from another
      // candidate.
      responding_node = responder_map.at(visited_node);
      if (responding_node)
        break;
      visited_nodes.push_back(visited_node);
      // Check if the node filter applies, which would mean we have found a
      // responding node.
      if (node_filter(visited_node)) {
        responding_node = visited_node;
        // Continue the iteration to collect the ancestors of the responder,
        // which we will need later.
        for (visited_node = ParentShadowHostOrOwner(visited_node); visited_node;
             visited_node = ParentShadowHostOrOwner(visited_node)) {
          HeapHashSet<Member<Node>>::AddResult add_result =
              ancestors_to_responders_set.insert(visited_node);
          if (!add_result.is_new_entry)
            break;
        }
        break;
      }
    }
    // Insert the detected responder for all the visited nodes.
    for (unsigned j = 0; j < visited_nodes.size(); j++)
      responder_map.insert(visited_nodes[j], responding_node);

    if (responding_node)
      candidates.push_back(node);
  }

  // We compile the list of component absolute quads instead of using the
  // bounding rect to be able to perform better hit-testing on inline links on
  // line-breaks.
  for (unsigned i = 0; i < candidates.size(); i++) {
    Node* candidate = candidates[i];
    // Skip nodes who's responders are ancestors of other responders. This gives
    // preference to the inner-most event-handlers. So that a link is always
    // preferred even when contained in an element that monitors all
    // click-events.
    Node* responding_node = responder_map.at(candidate);
    DCHECK(responding_node);
    if (ancestors_to_responders_set.Contains(responding_node))
      continue;
    // Consolidate bounds for editable content.
    if (editable_ancestors.Contains(candidate))
      continue;
    candidate->GetDocument().UpdateStyleAndLayoutTree();
    if (HasEditableStyle(*candidate)) {
      Node* replacement = candidate;
      Node* parent = candidate->ParentOrShadowHostNode();
      while (parent && HasEditableStyle(*parent)) {
        replacement = parent;
        if (editable_ancestors.Contains(replacement)) {
          replacement = nullptr;
          break;
        }
        editable_ancestors.insert(replacement);
        parent = parent->ParentOrShadowHostNode();
      }
      candidate = replacement;
    }
    if (candidate)
      append_subtargets_for_node(candidate, subtargets);
  }
}

// This returns quotient of the target area and its intersection with the touch
// area.  This will prioritize largest intersection and smallest area, while
// balancing the two against each other.
float ZoomableIntersectionQuotient(const IntPoint& touch_hotspot,
                                   const IntRect& touch_area,
                                   const SubtargetGeometry& subtarget) {
  IntRect rect = subtarget.GetNode()->GetDocument().View()->ConvertToRootFrame(
      subtarget.BoundingBox());

  // Check the rectangle is meaningful zoom target. It should at least contain
  // the hotspot.
  if (!rect.Contains(touch_hotspot))
    return std::numeric_limits<float>::infinity();
  IntRect intersection = rect;
  intersection.Intersect(touch_area);

  // Return the quotient of the intersection.
  return rect.Size().Area() / (float)intersection.Size().Area();
}

// Uses a hybrid of distance to adjust and intersect ratio, normalizing each
// score between 0 and 1 and combining them. The distance to adjust works best
// for disambiguating clicks on targets such as links, where the width may be
// significantly larger than the touch width.  Using area of overlap in such
// cases can lead to a bias towards shorter links. Conversely, percentage of
// overlap can provide strong confidence in tapping on a small target, where the
// overlap is often quite high, and works well for tightly packed controls.
float HybridDistanceFunction(const IntPoint& touch_hotspot,
                             const IntRect& touch_rect,
                             const SubtargetGeometry& subtarget) {
  IntRect rect = subtarget.GetNode()->GetDocument().View()->ConvertToRootFrame(
      subtarget.BoundingBox());

  float radius_squared = 0.25f * (touch_rect.Size().DiagonalLengthSquared());
  float distance_to_adjust_score =
      rect.DistanceSquaredToPoint(touch_hotspot) / radius_squared;

  int max_overlap_width = std::min(touch_rect.Width(), rect.Width());
  int max_overlap_height = std::min(touch_rect.Height(), rect.Height());
  float max_overlap_area = std::max(max_overlap_width * max_overlap_height, 1);
  rect.Intersect(touch_rect);
  float intersect_area = rect.Size().Area();
  float intersection_score = 1 - intersect_area / max_overlap_area;

  float hybrid_score = intersection_score + distance_to_adjust_score;

  return hybrid_score;
}

FloatPoint ConvertToRootFrame(LocalFrameView* view, FloatPoint pt) {
  int x = static_cast<int>(pt.X() + 0.5f);
  int y = static_cast<int>(pt.Y() + 0.5f);
  IntPoint adjusted = view->ConvertToRootFrame(IntPoint(x, y));
  return FloatPoint(adjusted.X(), adjusted.Y());
}

// Adjusts 'point' to the nearest point inside rect, and leaves it unchanged if
// already inside.
void AdjustPointToRect(FloatPoint& point, const IntRect& rect) {
  if (point.X() < rect.X())
    point.SetX(rect.X());
  else if (point.X() > rect.MaxX())
    point.SetX(rect.MaxX());

  if (point.Y() < rect.Y())
    point.SetY(rect.Y());
  else if (point.Y() > rect.MaxY())
    point.SetY(rect.MaxY());
}

bool SnapTo(const SubtargetGeometry& geom,
            const IntPoint& touch_point,
            const IntRect& touch_area,
            IntPoint& adjusted_point) {
  LocalFrameView* view = geom.GetNode()->GetDocument().View();
  FloatQuad quad = geom.Quad();

  if (quad.IsRectilinear()) {
    IntRect bounds = view->ConvertToRootFrame(geom.BoundingBox());
    if (bounds.Contains(touch_point)) {
      adjusted_point = touch_point;
      return true;
    }
    if (bounds.Intersects(touch_area)) {
      bounds.Intersect(touch_area);
      adjusted_point = bounds.Center();
      return true;
    }
    return false;
  }

  // The following code tries to adjust the point to place inside a both the
  // touchArea and the non-rectilinear quad.
  // FIXME: This will return the point inside the touch area that is the closest
  // to the quad center, but does not guarantee that the point will be inside
  // the quad. Corner-cases exist where the quad will intersect but this will
  // fail to adjust the point to somewhere in the intersection.

  FloatPoint p1 = ConvertToRootFrame(view, quad.P1());
  FloatPoint p2 = ConvertToRootFrame(view, quad.P2());
  FloatPoint p3 = ConvertToRootFrame(view, quad.P3());
  FloatPoint p4 = ConvertToRootFrame(view, quad.P4());
  quad = FloatQuad(p1, p2, p3, p4);

  if (quad.ContainsPoint(FloatPoint(touch_point))) {
    adjusted_point = touch_point;
    return true;
  }

  // Pull point towards the center of the element.
  FloatPoint center = quad.Center();

  AdjustPointToRect(center, touch_area);
  adjusted_point = RoundedIntPoint(center);

  return quad.ContainsPoint(FloatPoint(adjusted_point));
}

// A generic function for finding the target node with the lowest distance
// metric. A distance metric here is the result of a distance-like function,
// that computes how well the touch hits the node.  Distance functions could for
// instance be distance squared or area of intersection.
bool FindNodeWithLowestDistanceMetric(Node*& target_node,
                                      IntPoint& target_point,
                                      IntRect& target_area,
                                      const IntPoint& touch_hotspot,
                                      const IntRect& touch_area,
                                      SubtargetGeometryList& subtargets,
                                      DistanceFunction distance_function) {
  target_node = nullptr;
  float best_distance_metric = std::numeric_limits<float>::infinity();
  SubtargetGeometryList::const_iterator it = subtargets.begin();
  const SubtargetGeometryList::const_iterator end = subtargets.end();
  IntPoint adjusted_point;

  for (; it != end; ++it) {
    Node* node = it->GetNode();
    float distance_metric = distance_function(touch_hotspot, touch_area, *it);
    if (distance_metric < best_distance_metric) {
      if (SnapTo(*it, touch_hotspot, touch_area, adjusted_point)) {
        target_point = adjusted_point;
        target_area = it->BoundingBox();
        target_node = node;
        best_distance_metric = distance_metric;
      }
    } else if (distance_metric - best_distance_metric < kZeroTolerance) {
      if (SnapTo(*it, touch_hotspot, touch_area, adjusted_point)) {
        if (node->IsDescendantOf(target_node)) {
          // Try to always return the inner-most element.
          target_point = adjusted_point;
          target_node = node;
          target_area = it->BoundingBox();
        }
      }
    }
  }

  // As for HitTestResult.innerNode, we skip over pseudo elements.
  if (target_node && target_node->IsPseudoElement())
    target_node = target_node->ParentOrShadowHostNode();

  if (target_node) {
    target_area =
        target_node->GetDocument().View()->ConvertToRootFrame(target_area);
  }

  return (target_node);
}

}  // namespace touch_adjustment

bool FindBestClickableCandidate(Node*& target_node,
                                IntPoint& target_point,
                                const IntPoint& touch_hotspot,
                                const IntRect& touch_area,
                                const HeapVector<Member<Node>>& nodes) {
  IntRect target_area;
  touch_adjustment::SubtargetGeometryList subtargets;
  touch_adjustment::CompileSubtargetList(
      nodes, subtargets, touch_adjustment::NodeRespondsToTapGesture,
      touch_adjustment::AppendBasicSubtargetsForNode);
  return touch_adjustment::FindNodeWithLowestDistanceMetric(
      target_node, target_point, target_area, touch_hotspot, touch_area,
      subtargets, touch_adjustment::HybridDistanceFunction);
}

bool FindBestContextMenuCandidate(Node*& target_node,
                                  IntPoint& target_point,
                                  const IntPoint& touch_hotspot,
                                  const IntRect& touch_area,
                                  const HeapVector<Member<Node>>& nodes) {
  IntRect target_area;
  touch_adjustment::SubtargetGeometryList subtargets;
  touch_adjustment::CompileSubtargetList(
      nodes, subtargets, touch_adjustment::ProvidesContextMenuItems,
      touch_adjustment::AppendContextSubtargetsForNode);
  return touch_adjustment::FindNodeWithLowestDistanceMetric(
      target_node, target_point, target_area, touch_hotspot, touch_area,
      subtargets, touch_adjustment::HybridDistanceFunction);
}

LayoutSize GetHitTestRectForAdjustment(const LocalFrame& frame,
                                       const LayoutSize& touch_area) {
  float device_scale_factor =
      frame.GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
  // Check if zoom-for-dsf is enabled. If not, touch_area is in dip, so we don't
  // need to convert max_size_in_dip to physical pixel.
  if (frame.GetPage()->DeviceScaleFactorDeprecated() != 1)
    device_scale_factor = 1;

  float page_scale_factor = frame.GetPage()->PageScaleFactor();
  const LayoutSize max_size_in_dip(touch_adjustment::kMaxAdjustmentSizeDip,
                                   touch_adjustment::kMaxAdjustmentSizeDip);

  // (when use-zoom-for-dsf enabled) touch_area is in physical pixel scaled,
  // max_size_in_dip should be converted to physical pixel and scale too.
  return touch_area.ShrunkTo(max_size_in_dip *
                             (device_scale_factor / page_scale_factor));
}

}  // namespace blink
