// 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/input/ScrollManager.h"

#include "core/dom/DOMNodeIds.h"
#include "core/events/GestureEvent.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/TopControls.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/input/EventHandler.h"
#include "core/input/EventHandlingUtil.h"
#include "core/layout/LayoutBlock.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/loader/DocumentLoader.h"
#include "core/page/AutoscrollController.h"
#include "core/page/Page.h"
#include "core/page/scrolling/OverscrollController.h"
#include "core/page/scrolling/RootScrollerController.h"
#include "core/page/scrolling/ScrollState.h"
#include "core/paint/PaintLayer.h"
#include "platform/PlatformGestureEvent.h"
#include "wtf/PtrUtil.h"
#include <memory>

namespace blink {

ScrollManager::ScrollManager(LocalFrame* frame) : m_frame(frame) {
  clear();
}

void ScrollManager::clear() {
  m_lastGestureScrollOverWidget = false;
  m_scrollbarHandlingScrollGesture = nullptr;
  m_resizeScrollableArea = nullptr;
  m_offsetFromResizeCorner = LayoutSize();
  clearGestureScrollState();
}

DEFINE_TRACE(ScrollManager) {
  visitor->trace(m_frame);
  visitor->trace(m_scrollGestureHandlingNode);
  visitor->trace(m_previousGestureScrolledNode);
  visitor->trace(m_scrollbarHandlingScrollGesture);
  visitor->trace(m_resizeScrollableArea);
}

void ScrollManager::clearGestureScrollState() {
  m_scrollGestureHandlingNode = nullptr;
  m_previousGestureScrolledNode = nullptr;
  m_deltaConsumedForScrollSequence = false;
  m_currentScrollChain.clear();

  if (FrameHost* host = frameHost()) {
    bool resetX = true;
    bool resetY = true;
    host->overscrollController().resetAccumulated(resetX, resetY);
  }
}

void ScrollManager::stopAutoscroll() {
  if (AutoscrollController* controller = autoscrollController())
    controller->stopAutoscroll();
}

bool ScrollManager::middleClickAutoscrollInProgress() const {
  return autoscrollController() &&
         autoscrollController()->middleClickAutoscrollInProgress();
}

AutoscrollController* ScrollManager::autoscrollController() const {
  if (Page* page = m_frame->page())
    return &page->autoscrollController();
  return nullptr;
}

void ScrollManager::recomputeScrollChain(const Node& startNode,
                                         std::deque<int>& scrollChain) {
  scrollChain.clear();

  DCHECK(startNode.layoutObject());
  LayoutBox* curBox = startNode.layoutObject()->enclosingBox();

  // Scrolling propagates along the containing block chain and ends at the
  // RootScroller element. The RootScroller element will have a custom
  // applyScroll callback that scrolls the frame or element.
  while (curBox) {
    Node* curNode = curBox->node();
    Element* curElement = nullptr;

    // FIXME: this should reject more elements, as part of crbug.com/410974.
    if (curNode && curNode->isElementNode()) {
      curElement = toElement(curNode);
    } else if (curNode && curNode->isDocumentNode()) {
      // In normal circumastances, the documentElement will be the root
      // scroller but the documentElement itself isn't a containing block,
      // that'll be the document node rather than the element.
      curElement = m_frame->document()->documentElement();
      DCHECK(!curElement || isEffectiveRootScroller(*curElement));
    }

    if (curElement) {
      scrollChain.push_front(DOMNodeIds::idForNode(curElement));
      if (isEffectiveRootScroller(*curElement))
        break;
    }

    curBox = curBox->containingBlock();
  }
}

bool ScrollManager::logicalScroll(ScrollDirection direction,
                                  ScrollGranularity granularity,
                                  Node* startNode,
                                  Node* mousePressNode) {
  Node* node = startNode;

  if (!node)
    node = m_frame->document()->focusedElement();

  if (!node)
    node = mousePressNode;

  if ((!node || !node->layoutObject()) && m_frame->view() &&
      !m_frame->view()->layoutViewItem().isNull())
    node = m_frame->view()->layoutViewItem().node();

  if (!node)
    return false;

  m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  LayoutBox* curBox = node->layoutObject()->enclosingBox();
  while (curBox) {
    ScrollDirectionPhysical physicalDirection =
        toPhysicalDirection(direction, curBox->isHorizontalWritingMode(),
                            curBox->style()->isFlippedBlocksWritingMode());

    ScrollResult result =
        curBox->scroll(granularity, toScrollDelta(physicalDirection, 1));

    if (result.didScroll()) {
      setFrameWasScrolledByUser();
      return true;
    }

    curBox = curBox->containingBlock();
  }

  return false;
}

// TODO(bokan): This should be merged with logicalScroll assuming
// defaultSpaceEventHandler's chaining scroll can be done crossing frames.
bool ScrollManager::bubblingScroll(ScrollDirection direction,
                                   ScrollGranularity granularity,
                                   Node* startingNode,
                                   Node* mousePressNode) {
  // The layout needs to be up to date to determine if we can scroll. We may be
  // here because of an onLoad event, in which case the final layout hasn't been
  // performed yet.
  m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
  // FIXME: enable scroll customization in this case. See crbug.com/410974.
  if (logicalScroll(direction, granularity, startingNode, mousePressNode))
    return true;

  Frame* parentFrame = m_frame->tree().parent();
  if (!parentFrame || !parentFrame->isLocalFrame())
    return false;
  // FIXME: Broken for OOPI.
  return toLocalFrame(parentFrame)
      ->eventHandler()
      .bubblingScroll(direction, granularity, m_frame->deprecatedLocalOwner());
}

void ScrollManager::setFrameWasScrolledByUser() {
  if (DocumentLoader* documentLoader = m_frame->loader().documentLoader())
    documentLoader->initialScrollState().wasScrolledByUser = true;
}

void ScrollManager::customizedScroll(const Node& startNode,
                                     ScrollState& scrollState) {
  if (scrollState.fullyConsumed())
    return;

  if (scrollState.deltaX() || scrollState.deltaY())
    m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  if (m_currentScrollChain.empty())
    recomputeScrollChain(startNode, m_currentScrollChain);
  scrollState.setScrollChain(m_currentScrollChain);

  scrollState.distributeToScrollChainDescendant();
}

WebInputEventResult ScrollManager::handleGestureScrollBegin(
    const PlatformGestureEvent& gestureEvent) {
  Document* document = m_frame->document();

  if (document->layoutViewItem().isNull())
    return WebInputEventResult::NotHandled;

  // If there's no layoutObject on the node, send the event to the nearest
  // ancestor with a layoutObject.  Needed for <option> and <optgroup> elements
  // so we can touch scroll <select>s
  while (m_scrollGestureHandlingNode &&
         !m_scrollGestureHandlingNode->layoutObject())
    m_scrollGestureHandlingNode =
        m_scrollGestureHandlingNode->parentOrShadowHostNode();

  if (!m_scrollGestureHandlingNode)
    m_scrollGestureHandlingNode = m_frame->document()->documentElement();

  if (!m_scrollGestureHandlingNode)
    return WebInputEventResult::NotHandled;

  passScrollGestureEventToWidget(gestureEvent,
                                 m_scrollGestureHandlingNode->layoutObject());

  m_currentScrollChain.clear();
  std::unique_ptr<ScrollStateData> scrollStateData =
      wrapUnique(new ScrollStateData());
  scrollStateData->position_x = gestureEvent.position().x();
  scrollStateData->position_y = gestureEvent.position().y();
  scrollStateData->is_beginning = true;
  scrollStateData->from_user_input = true;
  scrollStateData->is_direct_manipulation =
      gestureEvent.source() == PlatformGestureSourceTouchscreen;
  scrollStateData->delta_consumed_for_scroll_sequence =
      m_deltaConsumedForScrollSequence;
  ScrollState* scrollState = ScrollState::create(std::move(scrollStateData));
  customizedScroll(*m_scrollGestureHandlingNode.get(), *scrollState);
  return WebInputEventResult::HandledSystem;
}

WebInputEventResult ScrollManager::handleGestureScrollUpdate(
    const PlatformGestureEvent& gestureEvent) {
  DCHECK_EQ(gestureEvent.type(), PlatformEvent::GestureScrollUpdate);

  // Negate the deltas since the gesture event stores finger movement and
  // scrolling occurs in the direction opposite the finger's movement
  // direction. e.g. Finger moving up has negative event delta but causes the
  // page to scroll down causing positive scroll delta.
  FloatSize delta(-gestureEvent.deltaX(), -gestureEvent.deltaY());
  FloatSize velocity(-gestureEvent.velocityX(), -gestureEvent.velocityY());
  FloatPoint position(gestureEvent.position());

  if (delta.isZero())
    return WebInputEventResult::NotHandled;

  Node* node = m_scrollGestureHandlingNode.get();

  if (!node)
    return WebInputEventResult::NotHandled;

  LayoutObject* layoutObject = node->layoutObject();
  if (!layoutObject)
    return WebInputEventResult::NotHandled;

  // Try to send the event to the correct view.
  WebInputEventResult result =
      passScrollGestureEventToWidget(gestureEvent, layoutObject);
  if (result != WebInputEventResult::NotHandled) {
    // FIXME: we should allow simultaneous scrolling of nested
    // iframes along perpendicular axes. See crbug.com/466991.
    m_deltaConsumedForScrollSequence = true;
    return result;
  }

  std::unique_ptr<ScrollStateData> scrollStateData =
      wrapUnique(new ScrollStateData());
  scrollStateData->delta_x = delta.width();
  scrollStateData->delta_y = delta.height();
  scrollStateData->delta_granularity =
      static_cast<double>(gestureEvent.deltaUnits());
  scrollStateData->velocity_x = velocity.width();
  scrollStateData->velocity_y = velocity.height();
  scrollStateData->position_x = position.x();
  scrollStateData->position_y = position.y();
  scrollStateData->should_propagate = !gestureEvent.preventPropagation();
  scrollStateData->is_in_inertial_phase =
      gestureEvent.inertialPhase() == ScrollInertialPhaseMomentum;
  scrollStateData->is_direct_manipulation =
      gestureEvent.source() == PlatformGestureSourceTouchscreen;
  scrollStateData->from_user_input = true;
  scrollStateData->delta_consumed_for_scroll_sequence =
      m_deltaConsumedForScrollSequence;
  ScrollState* scrollState = ScrollState::create(std::move(scrollStateData));
  if (m_previousGestureScrolledNode) {
    // The ScrollState needs to know what the current
    // native scrolling element is, so that for an
    // inertial scroll that shouldn't propagate, only the
    // currently scrolling element responds.
    DCHECK(m_previousGestureScrolledNode->isElementNode());
    scrollState->setCurrentNativeScrollingElement(
        toElement(m_previousGestureScrolledNode.get()));
  }
  customizedScroll(*node, *scrollState);
  m_previousGestureScrolledNode = scrollState->currentNativeScrollingElement();
  m_deltaConsumedForScrollSequence =
      scrollState->deltaConsumedForScrollSequence();

  bool didScrollX = scrollState->deltaX() != delta.width();
  bool didScrollY = scrollState->deltaY() != delta.height();

  if ((!m_previousGestureScrolledNode ||
       !isEffectiveRootScroller(*m_previousGestureScrolledNode)) &&
      frameHost())
    frameHost()->overscrollController().resetAccumulated(didScrollX,
                                                         didScrollY);

  if (didScrollX || didScrollY) {
    setFrameWasScrolledByUser();
    return WebInputEventResult::HandledSystem;
  }

  return WebInputEventResult::NotHandled;
}

WebInputEventResult ScrollManager::handleGestureScrollEnd(
    const PlatformGestureEvent& gestureEvent) {
  Node* node = m_scrollGestureHandlingNode;

  if (node) {
    passScrollGestureEventToWidget(gestureEvent, node->layoutObject());
    std::unique_ptr<ScrollStateData> scrollStateData =
        wrapUnique(new ScrollStateData());
    scrollStateData->is_ending = true;
    scrollStateData->is_in_inertial_phase =
        gestureEvent.inertialPhase() == ScrollInertialPhaseMomentum;
    scrollStateData->from_user_input = true;
    scrollStateData->is_direct_manipulation =
        gestureEvent.source() == PlatformGestureSourceTouchscreen;
    scrollStateData->delta_consumed_for_scroll_sequence =
        m_deltaConsumedForScrollSequence;
    ScrollState* scrollState = ScrollState::create(std::move(scrollStateData));
    customizedScroll(*node, *scrollState);
  }

  clearGestureScrollState();
  return WebInputEventResult::NotHandled;
}

FrameHost* ScrollManager::frameHost() const {
  if (!m_frame->page())
    return nullptr;

  return &m_frame->page()->frameHost();
}

WebInputEventResult ScrollManager::passScrollGestureEventToWidget(
    const PlatformGestureEvent& gestureEvent,
    LayoutObject* layoutObject) {
  DCHECK(gestureEvent.isScrollEvent());

  if (!m_lastGestureScrollOverWidget || !layoutObject ||
      !layoutObject->isLayoutPart())
    return WebInputEventResult::NotHandled;

  Widget* widget = toLayoutPart(layoutObject)->widget();

  if (!widget || !widget->isFrameView())
    return WebInputEventResult::NotHandled;

  return toFrameView(widget)->frame().eventHandler().handleGestureScrollEvent(
      gestureEvent);
}

bool ScrollManager::isEffectiveRootScroller(const Node& node) const {
  // The root scroller is the one Element on the page designated to perform
  // "viewport actions" like top controls movement and overscroll glow.
  if (!m_frame->document())
    return false;

  if (!node.isElementNode())
    return false;

  return node.isSameNode(
      m_frame->document()->rootScrollerController()->effectiveRootScroller());
}

WebInputEventResult ScrollManager::handleGestureScrollEvent(
    const PlatformGestureEvent& gestureEvent) {
  if (!m_frame->view())
    return WebInputEventResult::NotHandled;

  Node* eventTarget = nullptr;
  Scrollbar* scrollbar = nullptr;
  if (gestureEvent.type() != PlatformEvent::GestureScrollBegin) {
    scrollbar = m_scrollbarHandlingScrollGesture.get();
    eventTarget = m_scrollGestureHandlingNode.get();
  }

  if (!eventTarget) {
    Document* document = m_frame->document();
    if (document->layoutViewItem().isNull())
      return WebInputEventResult::NotHandled;

    FrameView* view = m_frame->view();
    LayoutPoint viewPoint = view->rootFrameToContents(gestureEvent.position());
    HitTestRequest request(HitTestRequest::ReadOnly);
    HitTestResult result(request, viewPoint);
    document->layoutViewItem().hitTest(result);

    eventTarget = result.innerNode();

    m_lastGestureScrollOverWidget = result.isOverWidget();
    m_scrollGestureHandlingNode = eventTarget;
    m_previousGestureScrolledNode = nullptr;
    m_deltaConsumedForScrollSequence = false;

    if (!scrollbar)
      scrollbar = result.scrollbar();
  }

  if (scrollbar) {
    bool shouldUpdateCapture = false;
    if (scrollbar->gestureEvent(gestureEvent, &shouldUpdateCapture)) {
      if (shouldUpdateCapture)
        m_scrollbarHandlingScrollGesture = scrollbar;
      return WebInputEventResult::HandledSuppressed;
    }
    m_scrollbarHandlingScrollGesture = nullptr;
  }

  if (eventTarget) {
    if (handleScrollGestureOnResizer(eventTarget, gestureEvent))
      return WebInputEventResult::HandledSuppressed;

    GestureEvent* gestureDomEvent =
        GestureEvent::create(eventTarget->document().domWindow(), gestureEvent);
    if (gestureDomEvent) {
      DispatchEventResult gestureDomEventResult =
          eventTarget->dispatchEvent(gestureDomEvent);
      if (gestureDomEventResult != DispatchEventResult::NotCanceled) {
        DCHECK(gestureDomEventResult !=
               DispatchEventResult::CanceledByEventHandler);
        return EventHandlingUtil::toWebInputEventResult(gestureDomEventResult);
      }
    }
  }

  switch (gestureEvent.type()) {
    case PlatformEvent::GestureScrollBegin:
      return handleGestureScrollBegin(gestureEvent);
    case PlatformEvent::GestureScrollUpdate:
      return handleGestureScrollUpdate(gestureEvent);
    case PlatformEvent::GestureScrollEnd:
      return handleGestureScrollEnd(gestureEvent);
    case PlatformEvent::GestureFlingStart:
    case PlatformEvent::GesturePinchBegin:
    case PlatformEvent::GesturePinchEnd:
    case PlatformEvent::GesturePinchUpdate:
      return WebInputEventResult::NotHandled;
    default:
      NOTREACHED();
      return WebInputEventResult::NotHandled;
  }
}

bool ScrollManager::isScrollbarHandlingGestures() const {
  return m_scrollbarHandlingScrollGesture.get();
}

bool ScrollManager::handleScrollGestureOnResizer(
    Node* eventTarget,
    const PlatformGestureEvent& gestureEvent) {
  if (gestureEvent.source() != PlatformGestureSourceTouchscreen)
    return false;

  if (gestureEvent.type() == PlatformEvent::GestureScrollBegin) {
    PaintLayer* layer = eventTarget->layoutObject()
                            ? eventTarget->layoutObject()->enclosingLayer()
                            : nullptr;
    IntPoint p = m_frame->view()->rootFrameToContents(gestureEvent.position());
    if (layer && layer->getScrollableArea() &&
        layer->getScrollableArea()->isPointInResizeControl(p,
                                                           ResizerForTouch)) {
      m_resizeScrollableArea = layer->getScrollableArea();
      m_resizeScrollableArea->setInResizeMode(true);
      m_offsetFromResizeCorner =
          LayoutSize(m_resizeScrollableArea->offsetFromResizeCorner(p));
      return true;
    }
  } else if (gestureEvent.type() == PlatformEvent::GestureScrollUpdate) {
    if (m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode()) {
      m_resizeScrollableArea->resize(gestureEvent, m_offsetFromResizeCorner);
      return true;
    }
  } else if (gestureEvent.type() == PlatformEvent::GestureScrollEnd) {
    if (m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode()) {
      m_resizeScrollableArea->setInResizeMode(false);
      m_resizeScrollableArea = nullptr;
      return false;
    }
  }

  return false;
}

bool ScrollManager::inResizeMode() const {
  return m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode();
}

void ScrollManager::resize(const PlatformEvent& evt) {
  m_resizeScrollableArea->resize(evt, m_offsetFromResizeCorner);
}

void ScrollManager::clearResizeScrollableArea(bool shouldNotBeNull) {
  if (shouldNotBeNull)
    DCHECK(m_resizeScrollableArea);

  if (m_resizeScrollableArea)
    m_resizeScrollableArea->setInResizeMode(false);
  m_resizeScrollableArea = nullptr;
}

void ScrollManager::setResizeScrollableArea(PaintLayer* layer, IntPoint p) {
  m_resizeScrollableArea = layer->getScrollableArea();
  m_resizeScrollableArea->setInResizeMode(true);
  m_offsetFromResizeCorner =
      LayoutSize(m_resizeScrollableArea->offsetFromResizeCorner(p));
}

bool ScrollManager::canHandleGestureEvent(
    const GestureEventWithHitTestResults& targetedEvent) {
  Scrollbar* scrollbar = targetedEvent.hitTestResult().scrollbar();

  if (scrollbar) {
    bool shouldUpdateCapture = false;
    if (scrollbar->gestureEvent(targetedEvent.event(), &shouldUpdateCapture)) {
      if (shouldUpdateCapture)
        m_scrollbarHandlingScrollGesture = scrollbar;
      return true;
    }
  }
  return false;
}

}  // namespace blink
