/*
 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
 * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
 * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
 *
 * 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/events/mouse_event.h"

#include "third_party/blink/public/platform/web_pointer_properties.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.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/frame/use_counter.h"
#include "third_party/blink/renderer/core/input/input_device_capabilities.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"

namespace blink {

namespace {

DoubleSize ContentsScrollOffset(AbstractView* abstract_view) {
  if (!abstract_view || !abstract_view->IsLocalDOMWindow())
    return DoubleSize();
  LocalFrame* frame = ToLocalDOMWindow(abstract_view)->GetFrame();
  if (!frame)
    return DoubleSize();
  ScrollableArea* scrollable_area =
      frame->View()->LayoutViewportScrollableArea();
  if (!scrollable_area)
    return DoubleSize();
  float scale_factor = frame->PageZoomFactor();
  return DoubleSize(scrollable_area->ScrollOffsetInt().Width() / scale_factor,
                    scrollable_area->ScrollOffsetInt().Height() / scale_factor);
}

float PageZoomFactor(const UIEvent* event) {
  if (!event->view() || !event->view()->IsLocalDOMWindow())
    return 1;
  LocalFrame* frame = ToLocalDOMWindow(event->view())->GetFrame();
  if (!frame)
    return 1;
  return frame->PageZoomFactor();
}

const LayoutObject* FindTargetLayoutObject(Node*& target_node) {
  LayoutObject* layout_object = target_node->GetLayoutObject();
  if (!layout_object || !layout_object->IsSVG())
    return layout_object;
  // If this is an SVG node, compute the offset to the padding box of the
  // outermost SVG root (== the closest ancestor that has a CSS layout box.)
  while (!layout_object->IsSVGRoot())
    layout_object = layout_object->Parent();
  // Update the target node to point to the SVG root.
  target_node = layout_object->GetNode();
  DCHECK(!target_node ||
         (target_node->IsSVGElement() &&
          ToSVGElement(*target_node).IsOutermostSVGSVGElement()));
  return layout_object;
}

unsigned ButtonsToWebInputEventModifiers(unsigned short buttons) {
  unsigned modifiers = 0;

  if (buttons &
      static_cast<unsigned short>(WebPointerProperties::Buttons::kLeft))
    modifiers |= WebInputEvent::kLeftButtonDown;
  if (buttons &
      static_cast<unsigned short>(WebPointerProperties::Buttons::kRight))
    modifiers |= WebInputEvent::kRightButtonDown;
  if (buttons &
      static_cast<unsigned short>(WebPointerProperties::Buttons::kMiddle))
    modifiers |= WebInputEvent::kMiddleButtonDown;
  if (buttons &
      static_cast<unsigned short>(WebPointerProperties::Buttons::kBack))
    modifiers |= WebInputEvent::kBackButtonDown;
  if (buttons &
      static_cast<unsigned short>(WebPointerProperties::Buttons::kForward))
    modifiers |= WebInputEvent::kForwardButtonDown;

  return modifiers;
}

}  // namespace

MouseEvent* MouseEvent::Create(ScriptState* script_state,
                               const AtomicString& type,
                               const MouseEventInit& initializer) {
  if (script_state && script_state->World().IsIsolatedWorld())
    UIEventWithKeyState::DidCreateEventInIsolatedWorld(
        initializer.ctrlKey(), initializer.altKey(), initializer.shiftKey(),
        initializer.metaKey());
  return new MouseEvent(type, initializer);
}

MouseEvent* MouseEvent::Create(const AtomicString& event_type,
                               const MouseEventInit& initializer,
                               TimeTicks platform_time_stamp,
                               SyntheticEventType synthetic_event_type,
                               WebMenuSourceType menu_source_type) {
  return new MouseEvent(event_type, initializer, platform_time_stamp,
                        synthetic_event_type, menu_source_type);
}

MouseEvent* MouseEvent::Create(const AtomicString& event_type,
                               AbstractView* view,
                               Event* underlying_event,
                               SimulatedClickCreationScope creation_scope) {
  WebInputEvent::Modifiers modifiers = WebInputEvent::kNoModifiers;
  if (UIEventWithKeyState* key_state_event =
          FindEventWithKeyState(underlying_event)) {
    modifiers = key_state_event->GetModifiers();
  }

  SyntheticEventType synthetic_type = kPositionless;
  MouseEventInit initializer;
  if (underlying_event && underlying_event->IsMouseEvent()) {
    synthetic_type = kRealOrIndistinguishable;
    MouseEvent* mouse_event = ToMouseEvent(underlying_event);
    initializer.setScreenX(mouse_event->screenX());
    initializer.setScreenY(mouse_event->screenY());
    initializer.setSourceCapabilities(
        view ? view->GetInputDeviceCapabilities()->FiresTouchEvents(false)
             : nullptr);
  }

  initializer.setBubbles(true);
  initializer.setCancelable(true);
  initializer.setView(view);
  initializer.setComposed(true);
  UIEventWithKeyState::SetFromWebInputEventModifiers(initializer, modifiers);
  initializer.setButtons(
      MouseEvent::WebInputEventModifiersToButtons(modifiers));

  TimeTicks timestamp = underlying_event ? underlying_event->PlatformTimeStamp()
                                         : CurrentTimeTicks();
  MouseEvent* created_event =
      new MouseEvent(event_type, initializer, timestamp, synthetic_type);

  created_event->SetTrusted(creation_scope ==
                            SimulatedClickCreationScope::kFromUserAgent);
  created_event->SetUnderlyingEvent(underlying_event);
  if (synthetic_type == kRealOrIndistinguishable) {
    MouseEvent* mouse_event = ToMouseEvent(created_event->UnderlyingEvent());
    created_event->InitCoordinates(mouse_event->clientX(),
                                   mouse_event->clientY());
  }

  return created_event;
}

MouseEvent::MouseEvent()
    : position_type_(PositionType::kPosition),
      has_cached_relative_position_(false),
      button_(0),
      buttons_(0),
      related_target_(nullptr),
      synthetic_event_type_(kRealOrIndistinguishable) {}

MouseEvent::MouseEvent(const AtomicString& event_type,
                       const MouseEventInit& initializer,
                       TimeTicks platform_time_stamp,
                       SyntheticEventType synthetic_event_type,
                       WebMenuSourceType menu_source_type)
    : UIEventWithKeyState(event_type, initializer, platform_time_stamp),
      screen_location_(
          DoublePoint(initializer.screenX(), initializer.screenY())),
      movement_delta_(
          IntPoint(initializer.movementX(), initializer.movementY())),
      position_type_(synthetic_event_type == kPositionless
                         ? PositionType::kPositionless
                         : PositionType::kPosition),
      button_(initializer.button()),
      buttons_(initializer.buttons()),
      related_target_(initializer.relatedTarget()),
      synthetic_event_type_(synthetic_event_type),
      region_(initializer.region()),
      menu_source_type_(menu_source_type) {
  InitCoordinates(initializer.clientX(), initializer.clientY());
  modifiers_ |= ButtonsToWebInputEventModifiers(buttons_);
}

void MouseEvent::InitCoordinates(const double client_x, const double client_y) {
  // Set up initial values for coordinates.
  // Correct values are computed lazily, see computeRelativePosition.
  client_location_ = DoublePoint(client_x, client_y);
  page_location_ = client_location_ + ContentsScrollOffset(view());

  layer_location_ = page_location_;
  offset_location_ = page_location_;

  ComputePageLocation();
  has_cached_relative_position_ = false;
}

void MouseEvent::SetCoordinatesFromWebPointerProperties(
    const WebPointerProperties& web_pointer_properties,
    const LocalDOMWindow* dom_window,
    MouseEventInit& initializer) {
  FloatPoint client_point;
  float scale_factor = 1.0f;
  if (dom_window && dom_window->GetFrame() && dom_window->GetFrame()->View()) {
    LocalFrame* frame = dom_window->GetFrame();
    FloatPoint page_point = frame->View()->ConvertFromRootFrame(
        web_pointer_properties.PositionInWidget());
    scale_factor = 1.0f / frame->PageZoomFactor();
    FloatPoint scroll_position(frame->View()->GetScrollOffset());
    client_point = page_point.ScaledBy(scale_factor);
    client_point.MoveBy(scroll_position.ScaledBy(-scale_factor));
  }

  initializer.setScreenX(web_pointer_properties.PositionInScreen().x);
  initializer.setScreenY(web_pointer_properties.PositionInScreen().y);
  initializer.setClientX(client_point.X());
  initializer.setClientY(client_point.Y());

  // TODO(nzolghadr): We need to scale movement attrinutes as well. But if we do
  // that here and round it to the int again it causes inconsistencies between
  // screenX/Y and cumulative movementX/Y.
  initializer.setMovementX(web_pointer_properties.movement_x);
  initializer.setMovementY(web_pointer_properties.movement_y);
}

MouseEvent::~MouseEvent() = default;

unsigned short MouseEvent::WebInputEventModifiersToButtons(unsigned modifiers) {
  unsigned short buttons = 0;

  if (modifiers & WebInputEvent::kLeftButtonDown)
    buttons |=
        static_cast<unsigned short>(WebPointerProperties::Buttons::kLeft);
  if (modifiers & WebInputEvent::kRightButtonDown) {
    buttons |=
        static_cast<unsigned short>(WebPointerProperties::Buttons::kRight);
  }
  if (modifiers & WebInputEvent::kMiddleButtonDown) {
    buttons |=
        static_cast<unsigned short>(WebPointerProperties::Buttons::kMiddle);
  }
  if (modifiers & WebInputEvent::kBackButtonDown)
    buttons |=
        static_cast<unsigned short>(WebPointerProperties::Buttons::kBack);
  if (modifiers & WebInputEvent::kForwardButtonDown) {
    buttons |=
        static_cast<unsigned short>(WebPointerProperties::Buttons::kForward);
  }

  return buttons;
}

void MouseEvent::initMouseEvent(ScriptState* script_state,
                                const AtomicString& type,
                                bool bubbles,
                                bool cancelable,
                                AbstractView* view,
                                int detail,
                                int screen_x,
                                int screen_y,
                                int client_x,
                                int client_y,
                                bool ctrl_key,
                                bool alt_key,
                                bool shift_key,
                                bool meta_key,
                                short button,
                                EventTarget* related_target,
                                unsigned short buttons) {
  if (IsBeingDispatched())
    return;

  if (script_state && script_state->World().IsIsolatedWorld())
    UIEventWithKeyState::DidCreateEventInIsolatedWorld(ctrl_key, alt_key,
                                                       shift_key, meta_key);

  InitModifiers(ctrl_key, alt_key, shift_key, meta_key);
  InitMouseEventInternal(type, bubbles, cancelable, view, detail, screen_x,
                         screen_y, client_x, client_y, GetModifiers(), button,
                         related_target, nullptr, buttons);
}

void MouseEvent::InitMouseEventInternal(
    const AtomicString& type,
    bool bubbles,
    bool cancelable,
    AbstractView* view,
    int detail,
    double screen_x,
    double screen_y,
    double client_x,
    double client_y,
    WebInputEvent::Modifiers modifiers,
    short button,
    EventTarget* related_target,
    InputDeviceCapabilities* source_capabilities,
    unsigned short buttons) {
  InitUIEventInternal(type, bubbles, cancelable, related_target, view, detail,
                      source_capabilities);

  screen_location_ = DoublePoint(screen_x, screen_y);
  button_ = button;
  buttons_ = buttons;
  related_target_ = related_target;
  modifiers_ = modifiers;

  InitCoordinates(client_x, client_y);

  // FIXME: SyntheticEventType is not set to RealOrIndistinguishable here.
}

const AtomicString& MouseEvent::InterfaceName() const {
  return EventNames::MouseEvent;
}

bool MouseEvent::IsMouseEvent() const {
  return true;
}

short MouseEvent::button() const {
  const AtomicString& event_name = type();
  if (button_ == -1 || event_name == EventTypeNames::mousemove ||
      event_name == EventTypeNames::mouseleave ||
      event_name == EventTypeNames::mouseenter ||
      event_name == EventTypeNames::mouseover ||
      event_name == EventTypeNames::mouseout) {
    return 0;
  }
  return button_;
}

unsigned MouseEvent::which() const {
  // For the DOM, the return values for left, middle and right mouse buttons are
  // 0, 1, 2, respectively.
  // For the Netscape "which" property, the return values for left, middle and
  // right mouse buttons are 1, 2, 3, respectively.
  // So we must add 1.
  return (unsigned)(button_ + 1);
}

Node* MouseEvent::toElement() const {
  // MSIE extension - "the object toward which the user is moving the mouse
  // pointer"
  if (type() == EventTypeNames::mouseout ||
      type() == EventTypeNames::mouseleave)
    return relatedTarget() ? relatedTarget()->ToNode() : nullptr;

  return target() ? target()->ToNode() : nullptr;
}

Node* MouseEvent::fromElement() const {
  // MSIE extension - "object from which activation or the mouse pointer is
  // exiting during the event" (huh?)
  if (type() != EventTypeNames::mouseout &&
      type() != EventTypeNames::mouseleave)
    return relatedTarget() ? relatedTarget()->ToNode() : nullptr;

  return target() ? target()->ToNode() : nullptr;
}

void MouseEvent::Trace(blink::Visitor* visitor) {
  visitor->Trace(related_target_);
  UIEventWithKeyState::Trace(visitor);
}

DispatchEventResult MouseEvent::DispatchEvent(EventDispatcher& dispatcher) {
  GetEventPath().AdjustForRelatedTarget(dispatcher.GetNode(), relatedTarget());

  bool is_click = type() == EventTypeNames::click;
  bool send_to_disabled_form_controls =
      RuntimeEnabledFeatures::SendMouseEventsDisabledFormControlsEnabled();

  if (send_to_disabled_form_controls && is_click &&
      GetEventPath().DisabledFormControlExistsInPath()) {
    return DispatchEventResult::kCanceledBeforeDispatch;
  }

  if (!isTrusted())
    return dispatcher.Dispatch();

  if (!send_to_disabled_form_controls &&
      IsDisabledFormControl(&dispatcher.GetNode())) {
    if (GetEventPath().HasEventListenersInPath(type())) {
      UseCounter::Count(dispatcher.GetNode().GetDocument(),
                        WebFeature::kDispatchMouseEventOnDisabledFormControl);
      if (type() == EventTypeNames::mousedown ||
          type() == EventTypeNames::mouseup) {
        UseCounter::Count(
            dispatcher.GetNode().GetDocument(),
            WebFeature::kDispatchMouseUpDownEventOnDisabledFormControl);
      }
    }
    return DispatchEventResult::kCanceledBeforeDispatch;
  }

  if (type().IsEmpty())
    return DispatchEventResult::kNotCanceled;  // Shouldn't happen.

  DCHECK(!target() || target() != relatedTarget());

  EventTarget* related_target = relatedTarget();

  DispatchEventResult dispatch_result = dispatcher.Dispatch();

  if (!is_click || detail() != 2)
    return dispatch_result;

  // Special case: If it's a double click event, we also send the dblclick
  // event. This is not part of the DOM specs, but is used for compatibility
  // with the ondblclick="" attribute. This is treated as a separate event in
  // other DOM-compliant browsers like Firefox, and so we do the same.
  MouseEvent* double_click_event = MouseEvent::Create();
  double_click_event->InitMouseEventInternal(
      EventTypeNames::dblclick, bubbles(), cancelable(), view(), detail(),
      screenX(), screenY(), clientX(), clientY(), GetModifiers(), button(),
      related_target, sourceCapabilities(), buttons());
  double_click_event->SetComposed(composed());

  // Inherit the trusted status from the original event.
  double_click_event->SetTrusted(isTrusted());
  if (DefaultHandled())
    double_click_event->SetDefaultHandled();
  DispatchEventResult double_click_dispatch_result =
      EventDispatcher::DispatchEvent(dispatcher.GetNode(), double_click_event);
  if (double_click_dispatch_result != DispatchEventResult::kNotCanceled)
    return double_click_dispatch_result;
  return dispatch_result;
}

void MouseEvent::ComputePageLocation() {
  LocalFrame* frame = view() && view()->IsLocalDOMWindow()
                          ? ToLocalDOMWindow(view())->GetFrame()
                          : nullptr;
  DoublePoint scaled_page_location =
      page_location_.ScaledBy(PageZoomFactor(this));
  if (frame && frame->View()) {
    absolute_location_ = frame->View()->DocumentToFrame(scaled_page_location);
  } else {
    absolute_location_ = scaled_page_location;
  }
}

void MouseEvent::ReceivedTarget() {
  has_cached_relative_position_ = false;
}

void MouseEvent::ComputeRelativePosition() {
  Node* target_node = target() ? target()->ToNode() : nullptr;
  if (!target_node)
    return;

  // Compute coordinates that are based on the target.
  layer_location_ = page_location_;
  offset_location_ = page_location_;
  float inverse_zoom_factor = 1 / PageZoomFactor(this);

  // Must have an updated layout tree for this math to work correctly.
  target_node->GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();

  // Adjust offsetLocation to be relative to the target's padding box.
  if (const LayoutObject* layout_object = FindTargetLayoutObject(target_node)) {
    FloatPoint local_pos = layout_object->AbsoluteToLocal(
        FloatPoint(AbsoluteLocation()), kUseTransforms);

    // Adding this here to address crbug.com/570666. Basically we'd like to
    // find the local coordinates relative to the padding box not the border
    // box.
    if (layout_object->IsBoxModelObject()) {
      const LayoutBoxModelObject* layout_box =
          ToLayoutBoxModelObject(layout_object);
      local_pos.Move(-layout_box->BorderLeft(), -layout_box->BorderTop());
    }

    offset_location_ = DoublePoint(local_pos);
    if (inverse_zoom_factor != 1.0f)
      offset_location_.Scale(inverse_zoom_factor, inverse_zoom_factor);
  }

  // Adjust layerLocation to be relative to the layer.
  // FIXME: event.layerX and event.layerY are poorly defined,
  // and probably don't always correspond to PaintLayer offsets.
  // https://bugs.webkit.org/show_bug.cgi?id=21868
  Node* n = target_node;
  while (n && !n->GetLayoutObject())
    n = n->parentNode();

  if (n) {
    DoublePoint scaled_page_location =
        page_location_.ScaledBy(PageZoomFactor(this));
    if (LocalFrameView* view = n->GetLayoutObject()->View()->GetFrameView())
      layer_location_ = view->DocumentToFrame(scaled_page_location);

    // FIXME: This logic is a wrong implementation of convertToLayerCoords.
    for (PaintLayer* layer = n->GetLayoutObject()->EnclosingLayer(); layer;
         layer = layer->Parent()) {
      layer_location_ -= DoubleSize(layer->Location().X().ToDouble(),
                                    layer->Location().Y().ToDouble());
    }
    if (inverse_zoom_factor != 1.0f)
      layer_location_.Scale(inverse_zoom_factor, inverse_zoom_factor);
  }

  has_cached_relative_position_ = true;
}

int MouseEvent::layerX() {
  if (!has_cached_relative_position_)
    ComputeRelativePosition();

  // TODO(mustaq): Remove the PointerEvent specific code when mouse has
  // fractional coordinates. See crbug.com/655786.
  return IsPointerEvent() ? layer_location_.X()
                          : static_cast<int>(layer_location_.X());
}

int MouseEvent::layerY() {
  if (!has_cached_relative_position_)
    ComputeRelativePosition();

  // TODO(mustaq): Remove the PointerEvent specific code when mouse has
  // fractional coordinates. See crbug.com/655786.
  return IsPointerEvent() ? layer_location_.Y()
                          : static_cast<int>(layer_location_.Y());
}

int MouseEvent::offsetX() {
  if (!HasPosition())
    return 0;
  if (!has_cached_relative_position_)
    ComputeRelativePosition();
  return std::round(offset_location_.X());
}

int MouseEvent::offsetY() {
  if (!HasPosition())
    return 0;
  if (!has_cached_relative_position_)
    ComputeRelativePosition();
  return std::round(offset_location_.Y());
}

}  // namespace blink
