// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math' as math;

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/physics.dart';

import 'binding.dart' show WidgetsBinding;
import 'framework.dart';
import 'overscroll_indicator.dart';
import 'scroll_metrics.dart';
import 'scroll_simulation.dart';

export 'package:flutter/physics.dart' show Simulation, ScrollSpringSimulation, Tolerance;

// Examples can assume:
// class FooScrollPhysics extends ScrollPhysics {
//   const FooScrollPhysics({ ScrollPhysics parent }): super(parent: parent);
// }
// class BarScrollPhysics extends ScrollPhysics {
//   const BarScrollPhysics({ ScrollPhysics parent }): super(parent: parent);
// }

/// Determines the physics of a [Scrollable] widget.
///
/// For example, determines how the [Scrollable] will behave when the user
/// reaches the maximum scroll extent or when the user stops scrolling.
///
/// When starting a physics [Simulation], the current scroll position and
/// velocity are used as the initial conditions for the particle in the
/// simulation. The movement of the particle in the simulation is then used to
/// determine the scroll position for the widget.
///
/// Instead of creating your own subclasses, [parent] can be used to combine
/// [ScrollPhysics] objects of different types to get the desired scroll physics.
/// For example:
///
/// ```dart
/// const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics())
/// ```
///
/// You can also use `applyTo`, which is useful when you already have
/// an instance of `ScrollPhysics`:
///
/// ```dart
/// ScrollPhysics physics = const BouncingScrollPhysics();
/// // ...
/// physics.applyTo(const AlwaysScrollableScrollPhysics())
/// ```
@immutable
class ScrollPhysics {
  /// Creates an object with the default scroll physics.
  const ScrollPhysics({ this.parent });

  /// If non-null, determines the default behavior for each method.
  ///
  /// If a subclass of [ScrollPhysics] does not override a method, that subclass
  /// will inherit an implementation from this base class that defers to
  /// [parent]. This mechanism lets you assemble novel combinations of
  /// [ScrollPhysics] subclasses at runtime. For example:
  ///
  /// ```dart
  /// const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics())
  /// ```
  ///
  /// will result in a [ScrollPhysics] that has the combined behavior
  /// of [BouncingScrollPhysics] and [AlwaysScrollableScrollPhysics]:
  /// behaviors that are not specified in [BouncingScrollPhysics]
  /// (e.g. [shouldAcceptUserOffset]) will defer to [AlwaysScrollableScrollPhysics].
  final ScrollPhysics? parent;

  /// If [parent] is null then return ancestor, otherwise recursively build a
  /// ScrollPhysics that has [ancestor] as its parent.
  ///
  /// This method is typically used to define [applyTo] methods like:
  ///
  /// ```dart
  /// FooScrollPhysics applyTo(ScrollPhysics ancestor) {
  ///   return FooScrollPhysics(parent: buildParent(ancestor));
  /// }
  /// ```
  @protected
  ScrollPhysics? buildParent(ScrollPhysics? ancestor) => parent?.applyTo(ancestor) ?? ancestor;

  /// If [parent] is null then return a [ScrollPhysics] with the same
  /// [runtimeType] where the [parent] has been replaced with the [ancestor].
  ///
  /// If this scroll physics object already has a parent, then this method
  /// is applied recursively and ancestor will appear at the end of the
  /// existing chain of parents.
  ///
  /// The returned object will combine some of the behaviors from this
  /// [ScrollPhysics] instance and some of the behaviors from [ancestor].
  ///
  /// {@tool snippet}
  ///
  /// In the following example, the [applyTo] method is used to combine the
  /// scroll physics of two [ScrollPhysics] objects, the resulting [ScrollPhysics]
  /// `x` has the same behavior as `y`:
  ///
  /// ```dart
  /// final FooScrollPhysics x = FooScrollPhysics().applyTo(BarScrollPhysics());
  /// const FooScrollPhysics y = FooScrollPhysics(parent: BarScrollPhysics());
  /// ```
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [buildParent], a utility method that's often used to define [applyTo]
  ///    methods for ScrollPhysics subclasses.
  ScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return ScrollPhysics(parent: buildParent(ancestor));
  }

  /// Used by [DragScrollActivity] and other user-driven activities to convert
  /// an offset in logical pixels as provided by the [DragUpdateDetails] into a
  /// delta to apply (subtract from the current position) using
  /// [ScrollActivityDelegate.setPixels].
  ///
  /// This is used by some [ScrollPosition] subclasses to apply friction during
  /// overscroll situations.
  ///
  /// This method must not adjust parts of the offset that are entirely within
  /// the bounds described by the given `position`.
  ///
  /// The given `position` is only valid during this method call. Do not keep a
  /// reference to it to use later, as the values may update, may not update, or
  /// may update to reflect an entirely unrelated scrollable.
  double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
    if (parent == null)
      return offset;
    return parent!.applyPhysicsToUserOffset(position, offset);
  }

  /// Whether the scrollable should let the user adjust the scroll offset, for
  /// example by dragging.
  ///
  /// By default, the user can manipulate the scroll offset if, and only if,
  /// there is actually content outside the viewport to reveal.
  ///
  /// The given `position` is only valid during this method call. Do not keep a
  /// reference to it to use later, as the values may update, may not update, or
  /// may update to reflect an entirely unrelated scrollable.
  bool shouldAcceptUserOffset(ScrollMetrics position) {
    if (parent == null)
      return position.pixels != 0.0 || position.minScrollExtent != position.maxScrollExtent;
    return parent!.shouldAcceptUserOffset(position);
  }

  /// Provides a heuristic to determine if expensive frame-bound tasks should be
  /// deferred.
  ///
  /// The velocity parameter must not be null, but may be positive, negative, or
  /// zero.
  ///
  /// The metrics parameter must not be null.
  ///
  /// The context parameter must not be null. It normally refers to the
  /// [BuildContext] of the widget making the call, such as an [Image] widget
  /// in a [ListView].
  ///
  /// This can be used to determine whether decoding or fetching complex data
  /// for the currently visible part of the viewport should be delayed
  /// to avoid doing work that will not have a chance to appear before a new
  /// frame is rendered.
  ///
  /// For example, a list of images could use this logic to delay decoding
  /// images until scrolling is slow enough to actually render the decoded
  /// image to the screen.
  ///
  /// The default implementation is a heuristic that compares the current
  /// scroll velocity in local logical pixels to the longest side of the window
  /// in physical pixels. Implementers can change this heuristic by overriding
  /// this method and providing their custom physics to the scrollable widget.
  /// For example, an application that changes the local coordinate system with
  /// a large perspective transform could provide a more or less aggressive
  /// heuristic depending on whether the transform was increasing or decreasing
  /// the overall scale between the global screen and local scrollable
  /// coordinate systems.
  ///
  /// The default implementation is stateless, and simply provides a point-in-
  /// time decision about how fast the scrollable is scrolling. It would always
  /// return true for a scrollable that is animating back and forth at high
  /// velocity in a loop. It is assumed that callers will handle such
  /// a case, or that a custom stateful implementation would be written that
  /// tracks the sign of the velocity on successive calls.
  ///
  /// Returning true from this method indicates that the current scroll velocity
  /// is great enough that expensive operations impacting the UI should be
  /// deferred.
  bool recommendDeferredLoading(double velocity, ScrollMetrics metrics, BuildContext context) {
    assert(velocity != null);
    assert(metrics != null);
    assert(context != null);
    if (parent == null) {
      final double maxPhysicalPixels = WidgetsBinding.instance!.window.physicalSize.longestSide;
      return velocity.abs() > maxPhysicalPixels;
    }
    return parent!.recommendDeferredLoading(velocity, metrics, context);
  }

  /// Determines the overscroll by applying the boundary conditions.
  ///
  /// Called by [ScrollPosition.applyBoundaryConditions], which is called by
  /// [ScrollPosition.setPixels] just before the [ScrollPosition.pixels] value
  /// is updated, to determine how much of the offset is to be clamped off and
  /// sent to [ScrollPosition.didOverscrollBy].
  ///
  /// The `value` argument is guaranteed to not equal the [ScrollMetrics.pixels]
  /// of the `position` argument when this is called.
  ///
  /// It is possible for this method to be called when the `position` describes
  /// an already-out-of-bounds position. In that case, the boundary conditions
  /// should usually only prevent a further increase in the extent to which the
  /// position is out of bounds, allowing a decrease to be applied successfully,
  /// so that (for instance) an animation can smoothly snap an out of bounds
  /// position to the bounds. See [BallisticScrollActivity].
  ///
  /// This method must not clamp parts of the offset that are entirely within
  /// the bounds described by the given `position`.
  ///
  /// The given `position` is only valid during this method call. Do not keep a
  /// reference to it to use later, as the values may update, may not update, or
  /// may update to reflect an entirely unrelated scrollable.
  ///
  /// ## Examples
  ///
  /// [BouncingScrollPhysics] returns zero. In other words, it allows scrolling
  /// past the boundary unhindered.
  ///
  /// [ClampingScrollPhysics] returns the amount by which the value is beyond
  /// the position or the boundary, whichever is furthest from the content. In
  /// other words, it disallows scrolling past the boundary, but allows
  /// scrolling back from being overscrolled, if for some reason the position
  /// ends up overscrolled.
  double applyBoundaryConditions(ScrollMetrics position, double value) {
    if (parent == null)
      return 0.0;
    return parent!.applyBoundaryConditions(position, value);
  }

  /// Describes what the scroll position should be given new viewport dimensions.
  ///
  /// This is called by [ScrollPosition.correctForNewDimensions].
  ///
  /// The arguments consist of the scroll metrics as they stood in the previous
  /// frame and the scroll metrics as they now stand after the last layout,
  /// including the position and minimum and maximum scroll extents; a flag
  /// indicating if the current [ScrollActivity] considers that the user is
  /// actively scrolling (see [ScrollActivity.isScrolling]); and the current
  /// velocity of the scroll position, if it is being driven by the scroll
  /// activity (this is 0.0 during a user gesture) (see
  /// [ScrollActivity.velocity]).
  ///
  /// The scroll metrics will be identical except for the
  /// [ScrollMetrics.minScrollExtent] and [ScrollMetrics.maxScrollExtent]. They
  /// are referred to as the `oldPosition` and `newPosition` (even though they
  /// both technically have the same "position", in the form of
  /// [ScrollMetrics.pixels]) because they are generated from the
  /// [ScrollPosition] before and after updating the scroll extents.
  ///
  /// If the returned value does not exactly match the scroll offset given by
  /// the `newPosition` argument (see [ScrollMetrics.pixels]), then the
  /// [ScrollPosition] will call [ScrollPosition.correctPixels] to update the
  /// new scroll position to the returned value, and layout will be re-run. This
  /// is expensive. The new value is subject to further manipulation by
  /// [applyBoundaryConditions].
  ///
  /// If the returned value _does_ match the `newPosition.pixels` scroll offset
  /// exactly, then [ScrollPosition.applyNewDimensions] will be called next. In
  /// that case, [applyBoundaryConditions] is not applied to the return value.
  ///
  /// The given [ScrollMetrics] are only valid during this method call. Do not
  /// keep references to them to use later, as the values may update, may not
  /// update, or may update to reflect an entirely unrelated scrollable.
  ///
  /// The default implementation returns the [ScrollMetrics.pixels] of the
  /// `newPosition`, which indicates that the current scroll offset is
  /// acceptable.
  ///
  /// See also:
  ///
  ///  * [RangeMaintainingScrollPhysics], which is enabled by default, and
  ///    which prevents unexpected changes to the content dimensions from
  ///    causing the scroll position to get any further out of bounds.
  double adjustPositionForNewDimensions({
    required ScrollMetrics oldPosition,
    required ScrollMetrics newPosition,
    required bool isScrolling,
    required double velocity,
  }) {
    if (parent == null)
      return newPosition.pixels;
    return parent!.adjustPositionForNewDimensions(oldPosition: oldPosition, newPosition: newPosition, isScrolling: isScrolling, velocity: velocity);
  }

  /// Returns a simulation for ballistic scrolling starting from the given
  /// position with the given velocity.
  ///
  /// This is used by [ScrollPositionWithSingleContext] in the
  /// [ScrollPositionWithSingleContext.goBallistic] method. If the result
  /// is non-null, [ScrollPositionWithSingleContext] will begin a
  /// [BallisticScrollActivity] with the returned value. Otherwise, it will
  /// begin an idle activity instead.
  ///
  /// The given `position` is only valid during this method call. Do not keep a
  /// reference to it to use later, as the values may update, may not update, or
  /// may update to reflect an entirely unrelated scrollable.
  Simulation? createBallisticSimulation(ScrollMetrics position, double velocity) {
    if (parent == null)
      return null;
    return parent!.createBallisticSimulation(position, velocity);
  }

  static final SpringDescription _kDefaultSpring = SpringDescription.withDampingRatio(
    mass: 0.5,
    stiffness: 100.0,
    ratio: 1.1,
  );

  /// The spring to use for ballistic simulations.
  SpringDescription get spring => parent?.spring ?? _kDefaultSpring;

  /// The default accuracy to which scrolling is computed.
  static final Tolerance _kDefaultTolerance = Tolerance(
    // TODO(ianh): Handle the case of the device pixel ratio changing.
    // TODO(ianh): Get this from the local MediaQuery not dart:ui's window object.
    velocity: 1.0 / (0.050 * WidgetsBinding.instance!.window.devicePixelRatio), // logical pixels per second
    distance: 1.0 / WidgetsBinding.instance!.window.devicePixelRatio, // logical pixels
  );

  /// The tolerance to use for ballistic simulations.
  Tolerance get tolerance => parent?.tolerance ?? _kDefaultTolerance;

  /// The minimum distance an input pointer drag must have moved to
  /// to be considered a scroll fling gesture.
  ///
  /// This value is typically compared with the distance traveled along the
  /// scrolling axis.
  ///
  /// See also:
  ///
  ///  * [VelocityTracker.getVelocityEstimate], which computes the velocity
  ///    of a press-drag-release gesture.
  double get minFlingDistance => parent?.minFlingDistance ?? kTouchSlop;

  /// The minimum velocity for an input pointer drag to be considered a
  /// scroll fling.
  ///
  /// This value is typically compared with the magnitude of fling gesture's
  /// velocity along the scrolling axis.
  ///
  /// See also:
  ///
  ///  * [VelocityTracker.getVelocityEstimate], which computes the velocity
  ///    of a press-drag-release gesture.
  double get minFlingVelocity => parent?.minFlingVelocity ?? kMinFlingVelocity;

  /// Scroll fling velocity magnitudes will be clamped to this value.
  double get maxFlingVelocity => parent?.maxFlingVelocity ?? kMaxFlingVelocity;

  /// Returns the velocity carried on repeated flings.
  ///
  /// The function is applied to the existing scroll velocity when another
  /// scroll drag is applied in the same direction.
  ///
  /// By default, physics for platforms other than iOS doesn't carry momentum.
  double carriedMomentum(double existingVelocity) {
    if (parent == null)
      return 0.0;
    return parent!.carriedMomentum(existingVelocity);
  }

  /// The minimum amount of pixel distance drags must move by to start motion
  /// the first time or after each time the drag motion stopped.
  ///
  /// If null, no minimum threshold is enforced.
  double? get dragStartDistanceMotionThreshold => parent?.dragStartDistanceMotionThreshold;

  /// Whether a viewport is allowed to change its scroll position implicitly in
  /// response to a call to [RenderObject.showOnScreen].
  ///
  /// [RenderObject.showOnScreen] is for example used to bring a text field
  /// fully on screen after it has received focus. This property controls
  /// whether the viewport associated with this object is allowed to change the
  /// scroll position to fulfill such a request.
  bool get allowImplicitScrolling => true;

  @override
  String toString() {
    if (parent == null)
      return objectRuntimeType(this, 'ScrollPhsyics');
    return '${objectRuntimeType(this, 'ScrollPhysics')} -> $parent';
  }
}

/// Scroll physics that attempt to keep the scroll position in range when the
/// contents change dimensions suddenly.
///
/// If the scroll position is already out of range, this attempts to maintain
/// the amount of overscroll or underscroll already present.
///
/// If the scroll activity is animating the scroll position, sudden changes to
/// the scroll dimensions are allowed to happen (so as to prevent animations
/// from jumping back and forth between in-range and out-of-range values).
///
/// These physics should be combined with other scroll physics, e.g.
/// [BouncingScrollPhysics] or [ClampingScrollPhysics], to obtain a complete
/// description of typical scroll physics. See [applyTo].
///
/// ## Implementation details
///
/// Specifically, these physics perform two adjustments.
///
/// The first is to maintain overscroll when the position is out of range.
///
/// The second is to enforce the boundary when the position is in range.
///
/// If the current velocity is non-zero, neither adjustment is made. The
/// assumption is that there is an ongoing animation and therefore
/// further changing the scroll position would disrupt the experience.
///
/// If the extents haven't changed, then the overscroll adjustment is
/// not made. The assumption is that if the position is overscrolled,
/// it is intentional, otherwise the position could not have reached
/// that position. (Consider [ClampingScrollPhysics] vs
/// [BouncingScrollPhysics] for example.)
///
/// If the position itself changed since the last animation frame,
/// then the overscroll is not maintained. The assumption is similar
/// to the previous case: the position would not have been placed out
/// of range unless it was intentional.
///
/// In addition, if the position changed and the boundaries were and
/// still are finite, then the boundary isn't enforced either, for
/// the same reason. However, if any of the boundaries were or are
/// now infinite, the boundary _is_ enforced, on the assumption that
/// infinite boundaries indicate a lazy-loading scroll view, which
/// cannot enforce boundaries while the full list has not loaded.
///
/// If the range was out of range, then the boundary is not enforced
/// even if the range is not maintained. If the range is maintained,
/// then the distance between the old position and the old boundary is
/// applied to the new boundary to obtain the new position.
///
/// If the range was in range, and the boundary is to be enforced,
/// then the new position is obtained by deferring to the other physics,
/// if any, and then clamped to the new range.
class RangeMaintainingScrollPhysics extends ScrollPhysics {
  /// Creates scroll physics that maintain the scroll position in range.
  const RangeMaintainingScrollPhysics({ ScrollPhysics? parent }) : super(parent: parent);

  @override
  RangeMaintainingScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return RangeMaintainingScrollPhysics(parent: buildParent(ancestor));
  }

  @override
  double adjustPositionForNewDimensions({
    required ScrollMetrics oldPosition,
    required ScrollMetrics newPosition,
    required bool isScrolling,
    required double velocity,
  }) {
    bool maintainOverscroll = true;
    bool enforceBoundary = true;
    if (velocity != 0.0) {
      // Don't try to adjust an animating position, the jumping around
      // would be distracting.
      maintainOverscroll = false;
      enforceBoundary = false;
    }
    if ((oldPosition.minScrollExtent == newPosition.minScrollExtent) &&
        (oldPosition.maxScrollExtent == newPosition.maxScrollExtent)) {
      // If the extents haven't changed then ignore overscroll.
      maintainOverscroll = false;
    }
    if (oldPosition.pixels != newPosition.pixels) {
      // If the position has been changed already, then it might have
      // been adjusted to expect new overscroll, so don't try to
      // maintain the relative overscroll.
      maintainOverscroll = false;
      if (oldPosition.minScrollExtent.isFinite && oldPosition.maxScrollExtent.isFinite &&
          newPosition.minScrollExtent.isFinite && newPosition.maxScrollExtent.isFinite) {
        // In addition, if the position changed then we only enforce
        // the new boundary if the previous boundary was not entirely
        // finite. A common case where the position changes while one
        // of the extents is infinite is a lazily-loaded list. (If the
        // boundaries were finite, and the position changed, then we
        // assume it was intentional.)
        enforceBoundary = false;
      }
    }
    if ((oldPosition.pixels < oldPosition.minScrollExtent) ||
        (oldPosition.pixels > oldPosition.maxScrollExtent)) {
      // If the old position was out of range, then we should
      // not try to keep the new position in range.
      enforceBoundary = false;
    }
    if (maintainOverscroll) {
      // Force the new position to be no more out of range
      // than it was before, if it was overscrolled.
      if (oldPosition.pixels < oldPosition.minScrollExtent) {
        final double oldDelta = oldPosition.minScrollExtent - oldPosition.pixels;
        return newPosition.minScrollExtent - oldDelta;
      }
      if (oldPosition.pixels > oldPosition.maxScrollExtent) {
        final double oldDelta = oldPosition.pixels - oldPosition.maxScrollExtent;
        return newPosition.maxScrollExtent + oldDelta;
      }
    }
    // If we're not forcing the overscroll, defer to other physics.
    double result = super.adjustPositionForNewDimensions(oldPosition: oldPosition, newPosition: newPosition, isScrolling: isScrolling, velocity: velocity);
    if (enforceBoundary) {
      // ...but if they put us out of range then reinforce the boundary.
      result = result.clamp(newPosition.minScrollExtent, newPosition.maxScrollExtent);
    }
    return result;
  }
}

/// Scroll physics for environments that allow the scroll offset to go beyond
/// the bounds of the content, but then bounce the content back to the edge of
/// those bounds.
///
/// This is the behavior typically seen on iOS.
///
/// [BouncingScrollPhysics] by itself will not create an overscroll effect if
/// the contents of the scroll view do not extend beyond the size of the
/// viewport. To create the overscroll and bounce effect regardless of the
/// length of your scroll view, combine with [AlwaysScrollableScrollPhysics].
///
/// {@tool snippet}
/// ```dart
/// BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics())
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [ScrollConfiguration], which uses this to provide the default
///    scroll behavior on iOS.
///  * [ClampingScrollPhysics], which is the analogous physics for Android's
///    clamping behavior.
///  * [ScrollPhysics], for more examples of combining [ScrollPhysics] objects
///    of different types to get the desired scroll physics.
class BouncingScrollPhysics extends ScrollPhysics {
  /// Creates scroll physics that bounce back from the edge.
  const BouncingScrollPhysics({ ScrollPhysics? parent }) : super(parent: parent);

  @override
  BouncingScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return BouncingScrollPhysics(parent: buildParent(ancestor));
  }

  /// The multiple applied to overscroll to make it appear that scrolling past
  /// the edge of the scrollable contents is harder than scrolling the list.
  /// This is done by reducing the ratio of the scroll effect output vs the
  /// scroll gesture input.
  ///
  /// This factor starts at 0.52 and progressively becomes harder to overscroll
  /// as more of the area past the edge is dragged in (represented by an increasing
  /// `overscrollFraction` which starts at 0 when there is no overscroll).
  double frictionFactor(double overscrollFraction) => 0.52 * math.pow(1 - overscrollFraction, 2);

  @override
  double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
    assert(offset != 0.0);
    assert(position.minScrollExtent <= position.maxScrollExtent);

    if (!position.outOfRange)
      return offset;

    final double overscrollPastStart = math.max(position.minScrollExtent - position.pixels, 0.0);
    final double overscrollPastEnd = math.max(position.pixels - position.maxScrollExtent, 0.0);
    final double overscrollPast = math.max(overscrollPastStart, overscrollPastEnd);
    final bool easing = (overscrollPastStart > 0.0 && offset < 0.0)
        || (overscrollPastEnd > 0.0 && offset > 0.0);

    final double friction = easing
        // Apply less resistance when easing the overscroll vs tensioning.
        ? frictionFactor((overscrollPast - offset.abs()) / position.viewportDimension)
        : frictionFactor(overscrollPast / position.viewportDimension);
    final double direction = offset.sign;

    return direction * _applyFriction(overscrollPast, offset.abs(), friction);
  }

  static double _applyFriction(double extentOutside, double absDelta, double gamma) {
    assert(absDelta > 0);
    double total = 0.0;
    if (extentOutside > 0) {
      final double deltaToLimit = extentOutside / gamma;
      if (absDelta < deltaToLimit)
        return absDelta * gamma;
      total += extentOutside;
      absDelta -= deltaToLimit;
    }
    return total + absDelta;
  }

  @override
  double applyBoundaryConditions(ScrollMetrics position, double value) => 0.0;

  @override
  Simulation? createBallisticSimulation(ScrollMetrics position, double velocity) {
    final Tolerance tolerance = this.tolerance;
    if (velocity.abs() >= tolerance.velocity || position.outOfRange) {
      return BouncingScrollSimulation(
        spring: spring,
        position: position.pixels,
        velocity: velocity,
        leadingExtent: position.minScrollExtent,
        trailingExtent: position.maxScrollExtent,
        tolerance: tolerance,
      );
    }
    return null;
  }

  // The ballistic simulation here decelerates more slowly than the one for
  // ClampingScrollPhysics so we require a more deliberate input gesture
  // to trigger a fling.
  @override
  double get minFlingVelocity => kMinFlingVelocity * 2.0;

  // Methodology:
  // 1- Use https://github.com/flutter/platform_tests/tree/master/scroll_overlay to test with
  //    Flutter and platform scroll views superimposed.
  // 3- If the scrollables stopped overlapping at any moment, adjust the desired
  //    output value of this function at that input speed.
  // 4- Feed new input/output set into a power curve fitter. Change function
  //    and repeat from 2.
  // 5- Repeat from 2 with medium and slow flings.
  /// Momentum build-up function that mimics iOS's scroll speed increase with repeated flings.
  ///
  /// The velocity of the last fling is not an important factor. Existing speed
  /// and (related) time since last fling are factors for the velocity transfer
  /// calculations.
  @override
  double carriedMomentum(double existingVelocity) {
    return existingVelocity.sign *
        math.min(0.000816 * math.pow(existingVelocity.abs(), 1.967).toDouble(), 40000.0);
  }

  // Eyeballed from observation to counter the effect of an unintended scroll
  // from the natural motion of lifting the finger after a scroll.
  @override
  double get dragStartDistanceMotionThreshold => 3.5;
}

/// Scroll physics for environments that prevent the scroll offset from reaching
/// beyond the bounds of the content.
///
/// This is the behavior typically seen on Android.
///
/// See also:
///
///  * [ScrollConfiguration], which uses this to provide the default
///    scroll behavior on Android.
///  * [BouncingScrollPhysics], which is the analogous physics for iOS' bouncing
///    behavior.
///  * [GlowingOverscrollIndicator], which is used by [ScrollConfiguration] to
///    provide the glowing effect that is usually found with this clamping effect
///    on Android. When using a [MaterialApp], the [GlowingOverscrollIndicator]'s
///    glow color is specified to use [ThemeData.accentColor].
class ClampingScrollPhysics extends ScrollPhysics {
  /// Creates scroll physics that prevent the scroll offset from exceeding the
  /// bounds of the content.
  const ClampingScrollPhysics({ ScrollPhysics? parent }) : super(parent: parent);

  @override
  ClampingScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return ClampingScrollPhysics(parent: buildParent(ancestor));
  }

  @override
  double applyBoundaryConditions(ScrollMetrics position, double value) {
    assert(() {
      if (value == position.pixels) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('$runtimeType.applyBoundaryConditions() was called redundantly.'),
          ErrorDescription(
            'The proposed new position, $value, is exactly equal to the current position of the '
            'given ${position.runtimeType}, ${position.pixels}.\n'
            'The applyBoundaryConditions method should only be called when the value is '
            'going to actually change the pixels, otherwise it is redundant.'
          ),
          DiagnosticsProperty<ScrollPhysics>('The physics object in question was', this, style: DiagnosticsTreeStyle.errorProperty),
          DiagnosticsProperty<ScrollMetrics>('The position object in question was', position, style: DiagnosticsTreeStyle.errorProperty)
        ]);
      }
      return true;
    }());
    if (value < position.pixels && position.pixels <= position.minScrollExtent) // underscroll
      return value - position.pixels;
    if (position.maxScrollExtent <= position.pixels && position.pixels < value) // overscroll
      return value - position.pixels;
    if (value < position.minScrollExtent && position.minScrollExtent < position.pixels) // hit top edge
      return value - position.minScrollExtent;
    if (position.pixels < position.maxScrollExtent && position.maxScrollExtent < value) // hit bottom edge
      return value - position.maxScrollExtent;
    return 0.0;
  }

  @override
  Simulation? createBallisticSimulation(ScrollMetrics position, double velocity) {
    final Tolerance tolerance = this.tolerance;
    if (position.outOfRange) {
      double? end;
      if (position.pixels > position.maxScrollExtent)
        end = position.maxScrollExtent;
      if (position.pixels < position.minScrollExtent)
        end = position.minScrollExtent;
      assert(end != null);
      return ScrollSpringSimulation(
        spring,
        position.pixels,
        end!,
        math.min(0.0, velocity),
        tolerance: tolerance,
      );
    }
    if (velocity.abs() < tolerance.velocity)
      return null;
    if (velocity > 0.0 && position.pixels >= position.maxScrollExtent)
      return null;
    if (velocity < 0.0 && position.pixels <= position.minScrollExtent)
      return null;
    return ClampingScrollSimulation(
      position: position.pixels,
      velocity: velocity,
      tolerance: tolerance,
    );
  }
}

/// Scroll physics that always lets the user scroll.
///
/// This overrides the default behavior which is to disable scrolling
/// when there is no content to scroll. It does not override the
/// handling of overscrolling.
///
/// On Android, overscrolls will be clamped by default and result in an
/// overscroll glow. On iOS, overscrolls will load a spring that will return the
/// scroll view to its normal range when released.
///
/// See also:
///
///  * [ScrollPhysics], which can be used instead of this class when the default
///    behavior is desired instead.
///  * [BouncingScrollPhysics], which provides the bouncing overscroll behavior
///    found on iOS.
///  * [ClampingScrollPhysics], which provides the clamping overscroll behavior
///    found on Android.
class AlwaysScrollableScrollPhysics extends ScrollPhysics {
  /// Creates scroll physics that always lets the user scroll.
  const AlwaysScrollableScrollPhysics({ ScrollPhysics? parent }) : super(parent: parent);

  @override
  AlwaysScrollableScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return AlwaysScrollableScrollPhysics(parent: buildParent(ancestor));
  }

  @override
  bool shouldAcceptUserOffset(ScrollMetrics position) => true;
}

/// Scroll physics that does not allow the user to scroll.
///
/// See also:
///
///  * [ScrollPhysics], which can be used instead of this class when the default
///    behavior is desired instead.
///  * [BouncingScrollPhysics], which provides the bouncing overscroll behavior
///    found on iOS.
///  * [ClampingScrollPhysics], which provides the clamping overscroll behavior
///    found on Android.
class NeverScrollableScrollPhysics extends ScrollPhysics {
  /// Creates scroll physics that does not let the user scroll.
  const NeverScrollableScrollPhysics({ ScrollPhysics? parent }) : super(parent: parent);

  @override
  NeverScrollableScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return NeverScrollableScrollPhysics(parent: buildParent(ancestor));
  }

  @override
  bool shouldAcceptUserOffset(ScrollMetrics position) => false;

  @override
  bool get allowImplicitScrolling => false;
}
