/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/page/page_widget_delegate.h"

#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/interactive_detector.h"
#include "third_party/blink/renderer/core/page/autoscroll_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
#include "third_party/blink/renderer/platform/wtf/time.h"

namespace blink {

void PageWidgetDelegate::Animate(Page& page,
                                 base::TimeTicks monotonic_frame_begin_time) {
  page.GetAutoscrollController().Animate();
  page.Animator().ServiceScriptedAnimations(monotonic_frame_begin_time);
}

void PageWidgetDelegate::UpdateLifecycle(
    Page& page,
    LocalFrame& root,
    WebWidget::LifecycleUpdate requested_update) {
  if (requested_update == WebWidget::LifecycleUpdate::kPrePaint) {
    page.Animator().UpdateLifecycleToPrePaintClean(root);
  } else {
    page.Animator().UpdateAllLifecyclePhases(root);
  }
}

static void PaintInternal(Page& page,
                          WebCanvas* canvas,
                          const WebRect& rect,
                          LocalFrame& root,
                          const GlobalPaintFlags global_paint_flags) {
  if (rect.IsEmpty())
    return;

  // FIXME: device scale factor settings are layering violations and should
  // not be used within Blink paint code.
  float scale_factor = page.DeviceScaleFactorDeprecated();
  canvas->save();
  canvas->scale(scale_factor, scale_factor);

  IntRect dirty_rect(rect);
  LocalFrameView* view = root.View();
  if (view) {
    DCHECK(view->GetLayoutView()->GetDocument().Lifecycle().GetState() ==
           DocumentLifecycle::kPaintClean);
    canvas->clipRect(dirty_rect);

    PaintRecordBuilder builder;
    builder.Context().SetDeviceScaleFactor(scale_factor);
    view->PaintWithLifecycleUpdate(builder.Context(), global_paint_flags,
                                   CullRect(dirty_rect));
    builder.EndRecording(*canvas);
  } else {
    PaintFlags flags;
    flags.setColor(SK_ColorWHITE);
    canvas->drawRect(dirty_rect, flags);
  }

  canvas->restore();
}

void PageWidgetDelegate::Paint(Page& page,
                               WebCanvas* canvas,
                               const WebRect& rect,
                               LocalFrame& root) {
  PaintInternal(page, canvas, rect, root, kGlobalPaintNormalPhase);
}

void PageWidgetDelegate::PaintIgnoringCompositing(Page& page,
                                                  WebCanvas* canvas,
                                                  const WebRect& rect,
                                                  LocalFrame& root) {
  PaintInternal(page, canvas, rect, root, kGlobalPaintFlattenCompositingLayers);
}

WebInputEventResult PageWidgetDelegate::HandleInputEvent(
    PageWidgetEventHandler& handler,
    const WebCoalescedInputEvent& coalesced_event,
    LocalFrame* root) {
  const WebInputEvent& event = coalesced_event.Event();
  if (root) {
    Document* document = root->GetDocument();
    DCHECK(document);

    InteractiveDetector* interactive_detector(
        InteractiveDetector::From(*document));

    // interactive_detector is null in the OOPIF case.
    // TODO(crbug.com/808089): report across OOPIFs.
    if (interactive_detector)
      interactive_detector->HandleForFirstInputDelay(event);
  }

  if (event.GetModifiers() & WebInputEvent::kIsTouchAccessibility &&
      WebInputEvent::IsMouseEventType(event.GetType())) {
    WebMouseEvent mouse_event = TransformWebMouseEvent(
        root->View(), static_cast<const WebMouseEvent&>(event));

    IntPoint doc_point(root->View()->ConvertFromRootFrame(
        FlooredIntPoint(mouse_event.PositionInRootFrame())));
    HitTestResult result = root->GetEventHandler().HitTestResultAtPoint(
        doc_point, HitTestRequest::kReadOnly | HitTestRequest::kActive);
    result.SetToShadowHostIfInRestrictedShadowRoot();
    if (result.InnerNodeFrame()) {
      Document* document = result.InnerNodeFrame()->GetDocument();
      if (document) {
        AXObjectCache* cache = document->ExistingAXObjectCache();
        if (cache) {
          cache->OnTouchAccessibilityHover(
              result.RoundedPointInInnerNodeFrame());
        }
      }
    }
  }

  switch (event.GetType()) {
    // FIXME: WebKit seems to always return false on mouse events processing
    // methods. For now we'll assume it has processed them (as we are only
    // interested in whether keyboard events are processed).
    // FIXME: Why do we return HandleSuppressed when there is no root or
    // the root is detached?
    case WebInputEvent::kMouseMove:
      if (!root || !root->View())
        return WebInputEventResult::kHandledSuppressed;
      handler.HandleMouseMove(*root, static_cast<const WebMouseEvent&>(event),
                              coalesced_event.GetCoalescedEventsPointers());
      return WebInputEventResult::kHandledSystem;
    case WebInputEvent::kMouseLeave:
      if (!root || !root->View())
        return WebInputEventResult::kHandledSuppressed;
      handler.HandleMouseLeave(*root, static_cast<const WebMouseEvent&>(event));
      return WebInputEventResult::kHandledSystem;
    case WebInputEvent::kMouseDown:
      if (!root || !root->View())
        return WebInputEventResult::kHandledSuppressed;
      handler.HandleMouseDown(*root, static_cast<const WebMouseEvent&>(event));
      return WebInputEventResult::kHandledSystem;
    case WebInputEvent::kMouseUp:
      if (!root || !root->View())
        return WebInputEventResult::kHandledSuppressed;
      handler.HandleMouseUp(*root, static_cast<const WebMouseEvent&>(event));
      return WebInputEventResult::kHandledSystem;
    case WebInputEvent::kMouseWheel:
      if (!root || !root->View())
        return WebInputEventResult::kNotHandled;
      return handler.HandleMouseWheel(
          *root, static_cast<const WebMouseWheelEvent&>(event));

    case WebInputEvent::kRawKeyDown:
    case WebInputEvent::kKeyDown:
    case WebInputEvent::kKeyUp:
      return handler.HandleKeyEvent(
          static_cast<const WebKeyboardEvent&>(event));

    case WebInputEvent::kChar:
      return handler.HandleCharEvent(
          static_cast<const WebKeyboardEvent&>(event));
    case WebInputEvent::kGestureScrollBegin:
    case WebInputEvent::kGestureScrollEnd:
    case WebInputEvent::kGestureScrollUpdate:
    case WebInputEvent::kGestureFlingStart:
    case WebInputEvent::kGestureFlingCancel:
    case WebInputEvent::kGestureTap:
    case WebInputEvent::kGestureTapUnconfirmed:
    case WebInputEvent::kGestureTapDown:
    case WebInputEvent::kGestureShowPress:
    case WebInputEvent::kGestureTapCancel:
    case WebInputEvent::kGestureDoubleTap:
    case WebInputEvent::kGestureTwoFingerTap:
    case WebInputEvent::kGestureLongPress:
    case WebInputEvent::kGestureLongTap:
      return handler.HandleGestureEvent(
          static_cast<const WebGestureEvent&>(event));

    case WebInputEvent::kPointerDown:
    case WebInputEvent::kPointerUp:
    case WebInputEvent::kPointerMove:
    case WebInputEvent::kPointerCancel:
    case WebInputEvent::kPointerCausedUaAction:
      if (!root || !root->View())
        return WebInputEventResult::kNotHandled;
      return handler.HandlePointerEvent(
          *root, static_cast<const WebPointerEvent&>(event),
          coalesced_event.GetCoalescedEventsPointers());

    case WebInputEvent::kTouchStart:
    case WebInputEvent::kTouchMove:
    case WebInputEvent::kTouchEnd:
    case WebInputEvent::kTouchCancel:
    case WebInputEvent::kTouchScrollStarted:
      NOTREACHED();
      return WebInputEventResult::kNotHandled;

    case WebInputEvent::kGesturePinchBegin:
    case WebInputEvent::kGesturePinchEnd:
    case WebInputEvent::kGesturePinchUpdate:
      // Touchscreen pinch events are currently not handled in main thread.
      // Once they are, these should be passed to |handleGestureEvent| similar
      // to gesture scroll events.
      return WebInputEventResult::kNotHandled;
    default:
      return WebInputEventResult::kNotHandled;
  }
}

// ----------------------------------------------------------------
// Default handlers for PageWidgetEventHandler

void PageWidgetEventHandler::HandleMouseMove(
    LocalFrame& main_frame,
    const WebMouseEvent& event,
    const std::vector<const WebInputEvent*>& coalesced_events) {
  WebMouseEvent transformed_event =
      TransformWebMouseEvent(main_frame.View(), event);
  main_frame.GetEventHandler().HandleMouseMoveEvent(
      transformed_event,
      TransformWebMouseEventVector(main_frame.View(), coalesced_events));
}

void PageWidgetEventHandler::HandleMouseLeave(LocalFrame& main_frame,
                                              const WebMouseEvent& event) {
  WebMouseEvent transformed_event =
      TransformWebMouseEvent(main_frame.View(), event);
  main_frame.GetEventHandler().HandleMouseLeaveEvent(transformed_event);
}

void PageWidgetEventHandler::HandleMouseDown(LocalFrame& main_frame,
                                             const WebMouseEvent& event) {
  WebMouseEvent transformed_event =
      TransformWebMouseEvent(main_frame.View(), event);
  main_frame.GetEventHandler().HandleMousePressEvent(transformed_event);
}

void PageWidgetEventHandler::HandleMouseUp(LocalFrame& main_frame,
                                           const WebMouseEvent& event) {
  WebMouseEvent transformed_event =
      TransformWebMouseEvent(main_frame.View(), event);
  main_frame.GetEventHandler().HandleMouseReleaseEvent(transformed_event);
}

WebInputEventResult PageWidgetEventHandler::HandleMouseWheel(
    LocalFrame& frame,
    const WebMouseWheelEvent& event) {
  WebMouseWheelEvent transformed_event =
      TransformWebMouseWheelEvent(frame.View(), event);
  return frame.GetEventHandler().HandleWheelEvent(transformed_event);
}

WebInputEventResult PageWidgetEventHandler::HandlePointerEvent(
    LocalFrame& main_frame,
    const WebPointerEvent& event,
    const std::vector<const WebInputEvent*>& coalesced_events) {
  WebPointerEvent transformed_event =
      TransformWebPointerEvent(main_frame.View(), event);
  return main_frame.GetEventHandler().HandlePointerEvent(
      transformed_event,
      TransformWebPointerEventVector(main_frame.View(), coalesced_events));
}

}  // namespace blink
