// Copyright 2014 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 "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"

#include <math.h>

#include <algorithm>

#include "base/bind.h"
#include "build/build_config.h"
#include "cc/input/input_handler.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_exponential.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/types/scroll_types.h"
#include "ui/gfx/geometry/vector2d_conversions.h"

/*
 * Copyright (C) 2011 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
 */

namespace blink {

namespace {
constexpr double kScrollVelocityZeroingTimeout = 0.10f;
constexpr double kRubberbandMinimumRequiredDeltaBeforeStretch = 10;
}  // namespace

ElasticOverscrollController::ElasticOverscrollController(
    cc::ScrollElasticityHelper* helper)
    : helper_(helper),
      state_(kStateInactive),
      received_overscroll_update_(false) {}

std::unique_ptr<ElasticOverscrollController>
ElasticOverscrollController::Create(cc::ScrollElasticityHelper* helper) {
#if defined(OS_WIN)
  return base::FeatureList::IsEnabled(features::kElasticOverscrollWin)
             ? std::make_unique<ElasticOverscrollControllerBezier>(helper)
             : nullptr;
#endif
  return std::make_unique<ElasticOverscrollControllerExponential>(helper);
}

void ElasticOverscrollController::ObserveRealScrollBegin(bool enter_momentum,
                                                         bool leave_momentum) {
  if (enter_momentum) {
    if (state_ == kStateInactive)
      state_ = kStateMomentumScroll;
  } else if (leave_momentum) {
    scroll_velocity_ = gfx::Vector2dF();
    last_scroll_event_timestamp_ = base::TimeTicks();
    state_ = kStateActiveScroll;
    pending_overscroll_delta_ = gfx::Vector2dF();
  }
}

void ElasticOverscrollController::ObserveScrollUpdate(
    const gfx::Vector2dF& event_delta,
    const gfx::Vector2dF& unused_scroll_delta,
    const base::TimeTicks& event_timestamp,
    const cc::OverscrollBehavior overscroll_behavior,
    bool has_momentum) {
  if (state_ == kStateMomentumAnimated || state_ == kStateInactive)
    return;

  if (!received_overscroll_update_ && !unused_scroll_delta.IsZero()) {
    overscroll_behavior_ = overscroll_behavior;
    received_overscroll_update_ = true;
  }

  UpdateVelocity(event_delta, event_timestamp);
  Overscroll(unused_scroll_delta);
  if (has_momentum && !helper_->StretchAmount().IsZero())
    EnterStateMomentumAnimated(event_timestamp);
}

void ElasticOverscrollController::ObserveRealScrollEnd(
    const base::TimeTicks event_timestamp) {
  if (state_ == kStateMomentumAnimated || state_ == kStateInactive)
    return;

  if (helper_->StretchAmount().IsZero()) {
    EnterStateInactive();
  } else {
    EnterStateMomentumAnimated(event_timestamp);
  }
}

void ElasticOverscrollController::ObserveGestureEventAndResult(
    const WebGestureEvent& gesture_event,
    const cc::InputHandlerScrollResult& scroll_result) {
  base::TimeTicks event_timestamp = gesture_event.TimeStamp();

  switch (gesture_event.GetType()) {
    case WebInputEvent::Type::kGestureScrollBegin: {
      received_overscroll_update_ = false;
      overscroll_behavior_ = cc::OverscrollBehavior();
      if (gesture_event.data.scroll_begin.synthetic)
        return;

      bool enter_momentum = gesture_event.data.scroll_begin.inertial_phase ==
                            WebGestureEvent::InertialPhaseState::kMomentum;
      bool leave_momentum =
          gesture_event.data.scroll_begin.inertial_phase ==
              WebGestureEvent::InertialPhaseState::kNonMomentum &&
          gesture_event.data.scroll_begin.delta_hint_units ==
              ui::ScrollGranularity::kScrollByPrecisePixel;
      ObserveRealScrollBegin(enter_momentum, leave_momentum);
      break;
    }
    case WebInputEvent::Type::kGestureScrollUpdate: {
      gfx::Vector2dF event_delta(-gesture_event.data.scroll_update.delta_x,
                                 -gesture_event.data.scroll_update.delta_y);
      bool has_momentum = gesture_event.data.scroll_update.inertial_phase ==
                          WebGestureEvent::InertialPhaseState::kMomentum;
      ObserveScrollUpdate(event_delta, scroll_result.unused_scroll_delta,
                          event_timestamp, scroll_result.overscroll_behavior,
                          has_momentum);
      break;
    }
    case WebInputEvent::Type::kGestureScrollEnd: {
      if (gesture_event.data.scroll_end.synthetic)
        return;
      ObserveRealScrollEnd(event_timestamp);
      break;
    }
    default:
      break;
  }
}

void ElasticOverscrollController::UpdateVelocity(
    const gfx::Vector2dF& event_delta,
    const base::TimeTicks& event_timestamp) {
  float time_delta =
      (event_timestamp - last_scroll_event_timestamp_).InSecondsF();
  if (time_delta < kScrollVelocityZeroingTimeout && time_delta > 0) {
    scroll_velocity_ = gfx::Vector2dF(event_delta.x() / time_delta,
                                      event_delta.y() / time_delta);
  } else {
    scroll_velocity_ = gfx::Vector2dF();
  }
  last_scroll_event_timestamp_ = event_timestamp;
}

void ElasticOverscrollController::Overscroll(
    const gfx::Vector2dF& overscroll_delta) {
  // The effect can be dynamically disabled by setting disallowing user
  // scrolling. When disabled, disallow active or momentum overscrolling, but
  // allow any current overscroll to animate back.
  if (!helper_->IsUserScrollable())
    return;

  gfx::Vector2dF adjusted_overscroll_delta =
      pending_overscroll_delta_ + overscroll_delta;
  pending_overscroll_delta_ = gfx::Vector2dF();

  // TODO (arakeri): Make this prefer the writing mode direction instead.
  // Only allow one direction to overscroll at a time, and slightly prefer
  // scrolling vertically by applying the equal case to delta_y.
  if (fabsf(overscroll_delta.y()) >= fabsf(overscroll_delta.x()))
    adjusted_overscroll_delta.set_x(0);
  else
    adjusted_overscroll_delta.set_y(0);

  // Don't allow overscrolling in a direction where scrolling is possible.
  if (!PinnedHorizontally(adjusted_overscroll_delta.x()))
    adjusted_overscroll_delta.set_x(0);
  if (!PinnedVertically(adjusted_overscroll_delta.y()))
    adjusted_overscroll_delta.set_y(0);

  // Don't allow overscrolling in a direction that has
  // OverscrollBehaviorTypeNone.
  if (overscroll_behavior_.x == cc::OverscrollBehavior::Type::kNone)
    adjusted_overscroll_delta.set_x(0);
  if (overscroll_behavior_.y == cc::OverscrollBehavior::Type::kNone)
    adjusted_overscroll_delta.set_y(0);

  // Require a minimum of 10 units of overscroll before starting the rubber-band
  // stretch effect, so that small stray motions don't trigger it. If that
  // minimum isn't met, save what remains in |pending_overscroll_delta_| for
  // the next event.
  gfx::Vector2dF old_stretch_amount = helper_->StretchAmount();
  gfx::Vector2dF stretch_scroll_force_delta;
  if (old_stretch_amount.x() != 0 ||
      fabsf(adjusted_overscroll_delta.x()) >=
          kRubberbandMinimumRequiredDeltaBeforeStretch) {
    stretch_scroll_force_delta.set_x(adjusted_overscroll_delta.x());
  } else {
    pending_overscroll_delta_.set_x(adjusted_overscroll_delta.x());
  }
  if (old_stretch_amount.y() != 0 ||
      fabsf(adjusted_overscroll_delta.y()) >=
          kRubberbandMinimumRequiredDeltaBeforeStretch) {
    stretch_scroll_force_delta.set_y(adjusted_overscroll_delta.y());
  } else {
    pending_overscroll_delta_.set_y(adjusted_overscroll_delta.y());
  }

  // Update the stretch amount according to the spring equations.
  if (stretch_scroll_force_delta.IsZero())
    return;
  stretch_scroll_force_ += stretch_scroll_force_delta;
  gfx::Vector2dF new_stretch_amount =
      StretchAmountForAccumulatedOverscroll(stretch_scroll_force_);
  helper_->SetStretchAmount(new_stretch_amount);
}

void ElasticOverscrollController::EnterStateInactive() {
  DCHECK_NE(kStateInactive, state_);
  DCHECK(helper_->StretchAmount().IsZero());
  state_ = kStateInactive;
  stretch_scroll_force_ = gfx::Vector2dF();
}

void ElasticOverscrollController::EnterStateMomentumAnimated(
    const base::TimeTicks& triggering_event_timestamp) {
  DCHECK_NE(kStateMomentumAnimated, state_);
  state_ = kStateMomentumAnimated;

  // If the scroller isn't stretched, there's nothing to animate.
  if (helper_->StretchAmount().IsZero())
    return;

  momentum_animation_start_time_ = triggering_event_timestamp;
  momentum_animation_initial_stretch_ = helper_->StretchAmount();
  momentum_animation_initial_velocity_ = scroll_velocity_;

  // Similarly to the logic in Overscroll, prefer vertical scrolling to
  // horizontal scrolling.
  if (fabsf(momentum_animation_initial_velocity_.y()) >=
      fabsf(momentum_animation_initial_velocity_.x()))
    momentum_animation_initial_velocity_.set_x(0);

  if (!CanScrollHorizontally())
    momentum_animation_initial_velocity_.set_x(0);

  if (!CanScrollVertically())
    momentum_animation_initial_velocity_.set_y(0);

  DidEnterMomentumAnimatedState();

  // TODO(crbug.com/394562): This can go away once input is batched to the front
  // of the frame? Then Animate() would always happen after this, so it would
  // have a chance to tick the animation there and would return if any
  // animations were active.
  helper_->RequestOneBeginFrame();
}

void ElasticOverscrollController::Animate(base::TimeTicks time) {
  if (state_ != kStateMomentumAnimated)
    return;

  // If the new stretch amount is near zero, set it directly to zero and enter
  // the inactive state.
  const gfx::Vector2dF new_stretch_amount = StretchAmountForTimeDelta(
      std::max(time - momentum_animation_start_time_, base::TimeDelta()));
  if (fabs(new_stretch_amount.x()) < 1 && fabs(new_stretch_amount.y()) < 1) {
    helper_->SetStretchAmount(gfx::Vector2dF());
    EnterStateInactive();
    return;
  }

  stretch_scroll_force_ =
      AccumulatedOverscrollForStretchAmount(new_stretch_amount);
  helper_->SetStretchAmount(new_stretch_amount);
  // TODO(danakj): Make this a return value back to the compositor to have it
  // schedule another frame and/or a draw. (Also, crbug.com/551138.)
  helper_->RequestOneBeginFrame();
}

bool ElasticOverscrollController::PinnedHorizontally(float direction) const {
  gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
  gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
  if (direction < 0)
    return scroll_offset.x() <= 0;
  if (direction > 0)
    return scroll_offset.x() >= max_scroll_offset.x();
  return false;
}

bool ElasticOverscrollController::PinnedVertically(float direction) const {
  gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
  gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
  if (direction < 0)
    return scroll_offset.y() <= 0;
  if (direction > 0)
    return scroll_offset.y() >= max_scroll_offset.y();
  return false;
}

bool ElasticOverscrollController::CanScrollHorizontally() const {
  return helper_->MaxScrollOffset().x() > 0;
}

bool ElasticOverscrollController::CanScrollVertically() const {
  return helper_->MaxScrollOffset().y() > 0;
}

void ElasticOverscrollController::ReconcileStretchAndScroll() {
  gfx::Vector2dF stretch = helper_->StretchAmount();
  if (stretch.IsZero())
    return;

  gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
  gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();

  // Compute stretch_adjustment which will be added to |stretch| and subtracted
  // from the |scroll_offset|.
  gfx::Vector2dF stretch_adjustment;
  if (stretch.x() < 0 && scroll_offset.x() > 0) {
    stretch_adjustment.set_x(
        std::min(-stretch.x(), static_cast<float>(scroll_offset.x())));
  }
  if (stretch.x() > 0 && scroll_offset.x() < max_scroll_offset.x()) {
    stretch_adjustment.set_x(std::max(
        -stretch.x(),
        static_cast<float>(scroll_offset.x() - max_scroll_offset.x())));
  }
  if (stretch.y() < 0 && scroll_offset.y() > 0) {
    stretch_adjustment.set_y(
        std::min(-stretch.y(), static_cast<float>(scroll_offset.y())));
  }
  if (stretch.y() > 0 && scroll_offset.y() < max_scroll_offset.y()) {
    stretch_adjustment.set_y(std::max(
        -stretch.y(),
        static_cast<float>(scroll_offset.y() - max_scroll_offset.y())));
  }

  if (stretch_adjustment.IsZero())
    return;

  gfx::Vector2dF new_stretch_amount = stretch + stretch_adjustment;
  helper_->ScrollBy(-stretch_adjustment);
  helper_->SetStretchAmount(new_stretch_amount);

  // Update the internal state for the active scroll to avoid discontinuities.
  if (state_ == kStateActiveScroll) {
    stretch_scroll_force_ =
        AccumulatedOverscrollForStretchAmount(new_stretch_amount);
  }
}

}  // namespace blink
