// 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:async' show Timer;
import 'dart:math' as math;

import 'package:flutter/foundation.dart';
import 'package:flutter/physics.dart' show nearEqual, Tolerance;
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';

import 'basic.dart';
import 'framework.dart';
import 'media_query.dart';
import 'notification_listener.dart';
import 'scroll_notification.dart';
import 'ticker_provider.dart';
import 'transitions.dart';

/// A visual indication that a scroll view has overscrolled.
///
/// A [GlowingOverscrollIndicator] listens for [ScrollNotification]s in order
/// to control the overscroll indication. These notifications are typically
/// generated by a [ScrollView], such as a [ListView] or a [GridView].
///
/// [GlowingOverscrollIndicator] generates [OverscrollIndicatorNotification]
/// before showing an overscroll indication. To prevent the indicator from
/// showing the indication, call [OverscrollIndicatorNotification.disallowGlow]
/// on the notification.
///
/// Created automatically by [ScrollBehavior.buildOverscrollIndicator] on platforms
/// (e.g., Android) that commonly use this type of overscroll indication.
///
/// In a [MaterialApp], the edge glow color is the overall theme's
/// [ColorScheme.secondary] color.
///
/// ## Customizing the Glow Position for Advanced Scroll Views
///
/// When building a [CustomScrollView] with a [GlowingOverscrollIndicator], the
/// indicator will apply to the entire scrollable area, regardless of what
/// slivers the CustomScrollView contains.
///
/// For example, if your CustomScrollView contains a SliverAppBar in the first
/// position, the GlowingOverscrollIndicator will overlay the SliverAppBar. To
/// manipulate the position of the GlowingOverscrollIndicator in this case,
/// you can either make use of a [NotificationListener] and provide a
/// [OverscrollIndicatorNotification.paintOffset] to the
/// notification, or use a [NestedScrollView].
///
/// {@tool dartpad}
/// This example demonstrates how to use a [NotificationListener] to manipulate
/// the placement of a [GlowingOverscrollIndicator] when building a
/// [CustomScrollView]. Drag the scrollable to see the bounds of the overscroll
/// indicator.
///
/// ** See code in examples/api/lib/widgets/overscroll_indicator/glowing_overscroll_indicator.0.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example demonstrates how to use a [NestedScrollView] to manipulate the
/// placement of a [GlowingOverscrollIndicator] when building a
/// [CustomScrollView]. Drag the scrollable to see the bounds of the overscroll
/// indicator.
///
/// ** See code in examples/api/lib/widgets/overscroll_indicator/glowing_overscroll_indicator.1.dart **
/// {@end-tool}
///
/// See also:
///
///  * [OverscrollIndicatorNotification], which can be used to manipulate the
///    glow position or prevent the glow from being painted at all.
///  * [NotificationListener], to listen for the
///    [OverscrollIndicatorNotification].
///  * [StretchingOverscrollIndicator], a Material Design overscroll indicator.
class GlowingOverscrollIndicator extends StatefulWidget {
  /// Creates a visual indication that a scroll view has overscrolled.
  ///
  /// In order for this widget to display an overscroll indication, the [child]
  /// widget must contain a widget that generates a [ScrollNotification], such
  /// as a [ListView] or a [GridView].
  ///
  /// The [showLeading], [showTrailing], [axisDirection], [color], and
  /// [notificationPredicate] arguments must not be null.
  const GlowingOverscrollIndicator({
    Key? key,
    this.showLeading = true,
    this.showTrailing = true,
    required this.axisDirection,
    required this.color,
    this.notificationPredicate = defaultScrollNotificationPredicate,
    this.child,
  }) : assert(showLeading != null),
       assert(showTrailing != null),
       assert(axisDirection != null),
       assert(color != null),
       assert(notificationPredicate != null),
       super(key: key);

  /// Whether to show the overscroll glow on the side with negative scroll
  /// offsets.
  ///
  /// For a vertical downwards viewport, this is the top side.
  ///
  /// Defaults to true.
  ///
  /// See [showTrailing] for the corresponding control on the other side of the
  /// viewport.
  final bool showLeading;

  /// Whether to show the overscroll glow on the side with positive scroll
  /// offsets.
  ///
  /// For a vertical downwards viewport, this is the bottom side.
  ///
  /// Defaults to true.
  ///
  /// See [showLeading] for the corresponding control on the other side of the
  /// viewport.
  final bool showTrailing;

  /// {@template flutter.overscroll.axisDirection}
  /// The direction of positive scroll offsets in the [Scrollable] whose
  /// overscrolls are to be visualized.
  /// {@endtemplate}
  final AxisDirection axisDirection;

  /// {@template flutter.overscroll.axis}
  /// The axis along which scrolling occurs in the [Scrollable] whose
  /// overscrolls are to be visualized.
  /// {@endtemplate}
  Axis get axis => axisDirectionToAxis(axisDirection);

  /// The color of the glow. The alpha channel is ignored.
  final Color color;

  /// {@template flutter.overscroll.notificationPredicate}
  /// A check that specifies whether a [ScrollNotification] should be
  /// handled by this widget.
  ///
  /// By default, checks whether `notification.depth == 0`. Set it to something
  /// else for more complicated layouts, such as nested [ScrollView]s.
  /// {@endtemplate}
  final ScrollNotificationPredicate notificationPredicate;

  /// The widget below this widget in the tree.
  ///
  /// The overscroll indicator will paint on top of this child. This child (and its
  /// subtree) should include a source of [ScrollNotification] notifications.
  ///
  /// Typically a [GlowingOverscrollIndicator] is created by a
  /// [ScrollBehavior.buildOverscrollIndicator] method, in which case
  /// the child is usually the one provided as an argument to that method.
  final Widget? child;

  @override
  State<GlowingOverscrollIndicator> createState() => _GlowingOverscrollIndicatorState();

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(EnumProperty<AxisDirection>('axisDirection', axisDirection));
    final String showDescription;
    if (showLeading && showTrailing) {
      showDescription = 'both sides';
    } else if (showLeading) {
      showDescription = 'leading side only';
    } else if (showTrailing) {
      showDescription = 'trailing side only';
    } else {
      showDescription = 'neither side (!)';
    }
    properties.add(MessageProperty('show', showDescription));
    properties.add(ColorProperty('color', color, showName: false));
  }
}

class _GlowingOverscrollIndicatorState extends State<GlowingOverscrollIndicator> with TickerProviderStateMixin {
  _GlowController? _leadingController;
  _GlowController? _trailingController;
  Listenable? _leadingAndTrailingListener;

  @override
  void initState() {
    super.initState();
    _leadingController = _GlowController(vsync: this, color: widget.color, axis: widget.axis);
    _trailingController = _GlowController(vsync: this, color: widget.color, axis: widget.axis);
    _leadingAndTrailingListener = Listenable.merge(<Listenable>[_leadingController!, _trailingController!]);
  }

  @override
  void didUpdateWidget(GlowingOverscrollIndicator oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.color != widget.color || oldWidget.axis != widget.axis) {
      _leadingController!.color = widget.color;
      _leadingController!.axis = widget.axis;
      _trailingController!.color = widget.color;
      _trailingController!.axis = widget.axis;
    }
  }

  Type? _lastNotificationType;
  final Map<bool, bool> _accepted = <bool, bool>{false: true, true: true};

  bool _handleScrollNotification(ScrollNotification notification) {
    if (!widget.notificationPredicate(notification))
      return false;

    // Update the paint offset with the current scroll position. This makes
    // sure that the glow effect correctly scrolls in line with the current
    // scroll, e.g. when scrolling in the opposite direction again to hide
    // the glow. Otherwise, the glow would always stay in a fixed position,
    // even if the top of the content already scrolled away.
    // For example (CustomScrollView with sliver before center), the scroll
    // extent is [-200.0, 300.0], scroll in the opposite direction with 10.0 pixels
    // before glow disappears, so the current pixels is -190.0,
    // in this case, we should move the glow up 10.0 pixels and should not
    // overflow the scrollable widget's edge. https://github.com/flutter/flutter/issues/64149.
    _leadingController!._paintOffsetScrollPixels =
      -math.min(notification.metrics.pixels - notification.metrics.minScrollExtent, _leadingController!._paintOffset);
    _trailingController!._paintOffsetScrollPixels =
      -math.min(notification.metrics.maxScrollExtent - notification.metrics.pixels, _trailingController!._paintOffset);

    if (notification is OverscrollNotification) {
      _GlowController? controller;
      if (notification.overscroll < 0.0) {
        controller = _leadingController;
      } else if (notification.overscroll > 0.0) {
        controller = _trailingController;
      } else {
        assert(false);
      }
      final bool isLeading = controller == _leadingController;
      if (_lastNotificationType is! OverscrollNotification) {
        final OverscrollIndicatorNotification confirmationNotification = OverscrollIndicatorNotification(leading: isLeading);
        confirmationNotification.dispatch(context);
        _accepted[isLeading] = confirmationNotification._accepted;
        if (_accepted[isLeading]!) {
          controller!._paintOffset = confirmationNotification.paintOffset;
        }
      }
      assert(controller != null);
      assert(notification.metrics.axis == widget.axis);
      if (_accepted[isLeading]!) {
        if (notification.velocity != 0.0) {
          assert(notification.dragDetails == null);
          controller!.absorbImpact(notification.velocity.abs());
        } else {
          assert(notification.overscroll != 0.0);
          if (notification.dragDetails != null) {
            assert(notification.dragDetails!.globalPosition != null);
            final RenderBox renderer = notification.context!.findRenderObject()! as RenderBox;
            assert(renderer != null);
            assert(renderer.hasSize);
            final Size size = renderer.size;
            final Offset position = renderer.globalToLocal(notification.dragDetails!.globalPosition);
            switch (notification.metrics.axis) {
              case Axis.horizontal:
                controller!.pull(notification.overscroll.abs(), size.width, position.dy.clamp(0.0, size.height), size.height);
                break;
              case Axis.vertical:
                controller!.pull(notification.overscroll.abs(), size.height, position.dx.clamp(0.0, size.width), size.width);
                break;
            }
          }
        }
      }
    } else if (notification is ScrollEndNotification || notification is ScrollUpdateNotification) {
      // Using dynamic here to avoid layer violations of importing
      // drag_details.dart from gestures.
      // ignore: avoid_dynamic_calls
      if ((notification as dynamic).dragDetails != null) {
        _leadingController!.scrollEnd();
        _trailingController!.scrollEnd();
      }
    }
    _lastNotificationType = notification.runtimeType;
    return false;
  }

  @override
  void dispose() {
    _leadingController!.dispose();
    _trailingController!.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return NotificationListener<ScrollNotification>(
      onNotification: _handleScrollNotification,
      child: RepaintBoundary(
        child: CustomPaint(
          foregroundPainter: _GlowingOverscrollIndicatorPainter(
            leadingController: widget.showLeading ? _leadingController : null,
            trailingController: widget.showTrailing ? _trailingController : null,
            axisDirection: widget.axisDirection,
            repaint: _leadingAndTrailingListener,
          ),
          child: RepaintBoundary(
            child: widget.child,
          ),
        ),
      ),
    );
  }
}

// The Glow logic is a port of the logic in the following file:
// https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/EdgeEffect.java
// as of December 2016.

enum _GlowState { idle, absorb, pull, recede }

class _GlowController extends ChangeNotifier {
  _GlowController({
    required TickerProvider vsync,
    required Color color,
    required Axis axis,
  }) : assert(vsync != null),
       assert(color != null),
       assert(axis != null),
       _color = color,
       _axis = axis {
    _glowController = AnimationController(vsync: vsync)
      ..addStatusListener(_changePhase);
    final Animation<double> decelerator = CurvedAnimation(
      parent: _glowController,
      curve: Curves.decelerate,
    )..addListener(notifyListeners);
    _glowOpacity = decelerator.drive(_glowOpacityTween);
    _glowSize = decelerator.drive(_glowSizeTween);
    _displacementTicker = vsync.createTicker(_tickDisplacement);
  }

  // animation of the main axis direction
  _GlowState _state = _GlowState.idle;
  late final AnimationController _glowController;
  Timer? _pullRecedeTimer;
  double _paintOffset = 0.0;
  double _paintOffsetScrollPixels = 0.0;

  // animation values
  final Tween<double> _glowOpacityTween = Tween<double>(begin: 0.0, end: 0.0);
  late final Animation<double> _glowOpacity;
  final Tween<double> _glowSizeTween = Tween<double>(begin: 0.0, end: 0.0);
  late final Animation<double> _glowSize;

  // animation of the cross axis position
  late final Ticker _displacementTicker;
  Duration? _displacementTickerLastElapsed;
  double _displacementTarget = 0.5;
  double _displacement = 0.5;

  // tracking the pull distance
  double _pullDistance = 0.0;

  Color get color => _color;
  Color _color;
  set color(Color value) {
    assert(color != null);
    if (color == value)
      return;
    _color = value;
    notifyListeners();
  }

  Axis get axis => _axis;
  Axis _axis;
  set axis(Axis value) {
    assert(axis != null);
    if (axis == value)
      return;
    _axis = value;
    notifyListeners();
  }

  static const Duration _recedeTime = Duration(milliseconds: 600);
  static const Duration _pullTime = Duration(milliseconds: 167);
  static const Duration _pullHoldTime = Duration(milliseconds: 167);
  static const Duration _pullDecayTime = Duration(milliseconds: 2000);
  static final Duration _crossAxisHalfTime = Duration(microseconds: (Duration.microsecondsPerSecond / 60.0).round());

  static const double _maxOpacity = 0.5;
  static const double _pullOpacityGlowFactor = 0.8;
  static const double _velocityGlowFactor = 0.00006;
  static const double _sqrt3 = 1.73205080757; // const math.sqrt(3)
  static const double _widthToHeightFactor = (3.0 / 4.0) * (2.0 - _sqrt3);

  // absorbed velocities are clamped to the range _minVelocity.._maxVelocity
  static const double _minVelocity = 100.0; // logical pixels per second
  static const double _maxVelocity = 10000.0; // logical pixels per second

  @override
  void dispose() {
    _glowController.dispose();
    _displacementTicker.dispose();
    _pullRecedeTimer?.cancel();
    super.dispose();
  }

  /// Handle a scroll slamming into the edge at a particular velocity.
  ///
  /// The velocity must be positive.
  void absorbImpact(double velocity) {
    assert(velocity >= 0.0);
    _pullRecedeTimer?.cancel();
    _pullRecedeTimer = null;
    velocity = velocity.clamp(_minVelocity, _maxVelocity);
    _glowOpacityTween.begin = _state == _GlowState.idle ? 0.3 : _glowOpacity.value;
    _glowOpacityTween.end = (velocity * _velocityGlowFactor).clamp(_glowOpacityTween.begin!, _maxOpacity);
    _glowSizeTween.begin = _glowSize.value;
    _glowSizeTween.end = math.min(0.025 + 7.5e-7 * velocity * velocity, 1.0);
    _glowController.duration = Duration(milliseconds: (0.15 + velocity * 0.02).round());
    _glowController.forward(from: 0.0);
    _displacement = 0.5;
    _state = _GlowState.absorb;
  }

  /// Handle a user-driven overscroll.
  ///
  /// The `overscroll` argument should be the scroll distance in logical pixels,
  /// the `extent` argument should be the total dimension of the viewport in the
  /// main axis in logical pixels, the `crossAxisOffset` argument should be the
  /// distance from the leading (left or top) edge of the cross axis of the
  /// viewport, and the `crossExtent` should be the size of the cross axis. For
  /// example, a pull of 50 pixels up the middle of a 200 pixel high and 100
  /// pixel wide vertical viewport should result in a call of `pull(50.0, 200.0,
  /// 50.0, 100.0)`. The `overscroll` value should be positive regardless of the
  /// direction.
  void pull(double overscroll, double extent, double crossAxisOffset, double crossExtent) {
    _pullRecedeTimer?.cancel();
    _pullDistance += overscroll / 200.0; // This factor is magic. Not clear why we need it to match Android.
    _glowOpacityTween.begin = _glowOpacity.value;
    _glowOpacityTween.end = math.min(_glowOpacity.value + overscroll / extent * _pullOpacityGlowFactor, _maxOpacity);
    final double height = math.min(extent, crossExtent * _widthToHeightFactor);
    _glowSizeTween.begin = _glowSize.value;
    _glowSizeTween.end = math.max(1.0 - 1.0 / (0.7 * math.sqrt(_pullDistance * height)), _glowSize.value);
    _displacementTarget = crossAxisOffset / crossExtent;
    if (_displacementTarget != _displacement) {
      if (!_displacementTicker.isTicking) {
        assert(_displacementTickerLastElapsed == null);
        _displacementTicker.start();
      }
    } else {
      _displacementTicker.stop();
      _displacementTickerLastElapsed = null;
    }
    _glowController.duration = _pullTime;
    if (_state != _GlowState.pull) {
      _glowController.forward(from: 0.0);
      _state = _GlowState.pull;
    } else {
      if (!_glowController.isAnimating) {
        assert(_glowController.value == 1.0);
        notifyListeners();
      }
    }
    _pullRecedeTimer = Timer(_pullHoldTime, () => _recede(_pullDecayTime));
  }

  void scrollEnd() {
    if (_state == _GlowState.pull)
      _recede(_recedeTime);
  }

  void _changePhase(AnimationStatus status) {
    if (status != AnimationStatus.completed)
      return;
    switch (_state) {
      case _GlowState.absorb:
        _recede(_recedeTime);
        break;
      case _GlowState.recede:
        _state = _GlowState.idle;
        _pullDistance = 0.0;
        break;
      case _GlowState.pull:
      case _GlowState.idle:
        break;
    }
  }

  void _recede(Duration duration) {
    if (_state == _GlowState.recede || _state == _GlowState.idle)
      return;
    _pullRecedeTimer?.cancel();
    _pullRecedeTimer = null;
    _glowOpacityTween.begin = _glowOpacity.value;
    _glowOpacityTween.end = 0.0;
    _glowSizeTween.begin = _glowSize.value;
    _glowSizeTween.end = 0.0;
    _glowController.duration = duration;
    _glowController.forward(from: 0.0);
    _state = _GlowState.recede;
  }

  void _tickDisplacement(Duration elapsed) {
    if (_displacementTickerLastElapsed != null) {
      final double t = (elapsed.inMicroseconds - _displacementTickerLastElapsed!.inMicroseconds).toDouble();
      _displacement = _displacementTarget - (_displacementTarget - _displacement) * math.pow(2.0, -t / _crossAxisHalfTime.inMicroseconds);
      notifyListeners();
    }
    if (nearEqual(_displacementTarget, _displacement, Tolerance.defaultTolerance.distance)) {
      _displacementTicker.stop();
      _displacementTickerLastElapsed = null;
    } else {
      _displacementTickerLastElapsed = elapsed;
    }
  }

  void paint(Canvas canvas, Size size) {
    if (_glowOpacity.value == 0.0)
      return;
    final double baseGlowScale = size.width > size.height ? size.height / size.width : 1.0;
    final double radius = size.width * 3.0 / 2.0;
    final double height = math.min(size.height, size.width * _widthToHeightFactor);
    final double scaleY = _glowSize.value * baseGlowScale;
    final Rect rect = Rect.fromLTWH(0.0, 0.0, size.width, height);
    final Offset center = Offset((size.width / 2.0) * (0.5 + _displacement), height - radius);
    final Paint paint = Paint()..color = color.withOpacity(_glowOpacity.value);
    canvas.save();
    canvas.translate(0.0, _paintOffset + _paintOffsetScrollPixels);
    canvas.scale(1.0, scaleY);
    canvas.clipRect(rect);
    canvas.drawCircle(center, radius, paint);
    canvas.restore();
  }
}

class _GlowingOverscrollIndicatorPainter extends CustomPainter {
  _GlowingOverscrollIndicatorPainter({
    this.leadingController,
    this.trailingController,
    required this.axisDirection,
    Listenable? repaint,
  }) : super(
    repaint: repaint,
  );

  /// The controller for the overscroll glow on the side with negative scroll offsets.
  ///
  /// For a vertical downwards viewport, this is the top side.
  final _GlowController? leadingController;

  /// The controller for the overscroll glow on the side with positive scroll offsets.
  ///
  /// For a vertical downwards viewport, this is the bottom side.
  final _GlowController? trailingController;

  /// The direction of the viewport.
  final AxisDirection axisDirection;

  static const double piOver2 = math.pi / 2.0;

  void _paintSide(Canvas canvas, Size size, _GlowController? controller, AxisDirection axisDirection, GrowthDirection growthDirection) {
    if (controller == null)
      return;
    switch (applyGrowthDirectionToAxisDirection(axisDirection, growthDirection)) {
      case AxisDirection.up:
        controller.paint(canvas, size);
        break;
      case AxisDirection.down:
        canvas.save();
        canvas.translate(0.0, size.height);
        canvas.scale(1.0, -1.0);
        controller.paint(canvas, size);
        canvas.restore();
        break;
      case AxisDirection.left:
        canvas.save();
        canvas.rotate(piOver2);
        canvas.scale(1.0, -1.0);
        controller.paint(canvas, Size(size.height, size.width));
        canvas.restore();
        break;
      case AxisDirection.right:
        canvas.save();
        canvas.translate(size.width, 0.0);
        canvas.rotate(piOver2);
        controller.paint(canvas, Size(size.height, size.width));
        canvas.restore();
        break;
    }
  }

  @override
  void paint(Canvas canvas, Size size) {
    _paintSide(canvas, size, leadingController, axisDirection, GrowthDirection.reverse);
    _paintSide(canvas, size, trailingController, axisDirection, GrowthDirection.forward);
  }

  @override
  bool shouldRepaint(_GlowingOverscrollIndicatorPainter oldDelegate) {
    return oldDelegate.leadingController != leadingController
        || oldDelegate.trailingController != trailingController;
  }
}

/// A Material Design visual indication that a scroll view has overscrolled.
///
/// A [StretchingOverscrollIndicator] listens for [ScrollNotification]s in order
/// to stretch the content of the [Scrollable]. These notifications are typically
/// generated by a [ScrollView], such as a [ListView] or a [GridView].
///
/// When triggered, the [StretchingOverscrollIndicator] generates an
/// [OverscrollIndicatorNotification] before showing an overscroll indication.
/// To prevent the indicator from showing the indication, call
/// [OverscrollIndicatorNotification.disallowIndicator] on the notification.
///
/// Created by [ScrollBehavior.buildOverscrollIndicator] on platforms
/// (e.g., Android) that commonly use this type of overscroll indication when
/// [ScrollBehavior.androidOverscrollIndicator] is
/// [AndroidOverscrollIndicator.stretch]. Otherwise, the default
/// [GlowingOverscrollIndicator] is applied.
///
/// See also:
///
///  * [OverscrollIndicatorNotification], which can be used to prevent the stretch
///    effect from being applied at all.
///  * [NotificationListener], to listen for the
///    [OverscrollIndicatorNotification].
///  * [GlowingOverscrollIndicator], the default overscroll indicator for
///    [TargetPlatform.android] and [TargetPlatform.fuchsia].
class StretchingOverscrollIndicator extends StatefulWidget {
  /// Creates a visual indication that a scroll view has overscrolled by
  /// applying a stretch transformation to the content.
  ///
  /// In order for this widget to display an overscroll indication, the [child]
  /// widget must contain a widget that generates a [ScrollNotification], such
  /// as a [ListView] or a [GridView].
  ///
  /// The [axisDirection] and [notificationPredicate] arguments must not be null.
  const StretchingOverscrollIndicator({
    Key? key,
    required this.axisDirection,
    this.notificationPredicate = defaultScrollNotificationPredicate,
    this.child,
  }) : assert(axisDirection != null),
       assert(notificationPredicate != null),
       super(key: key);

  /// {@macro flutter.overscroll.axisDirection}
  final AxisDirection axisDirection;

  /// {@macro flutter.overscroll.axis}
  Axis get axis => axisDirectionToAxis(axisDirection);

  /// {@macro flutter.overscroll.notificationPredicate}
  final ScrollNotificationPredicate notificationPredicate;

  /// The widget below this widget in the tree.
  ///
  /// The overscroll indicator will apply a stretch effect to this child. This
  /// child (and its subtree) should include a source of [ScrollNotification]
  /// notifications.
  ///
  /// Typically a [StretchingOverscrollIndicator] is created by a
  /// [ScrollBehavior.buildOverscrollIndicator] method when opted-in using the
  /// [ScrollBehavior.androidOverscrollIndicator] flag. In this case
  /// the child is usually the one provided as an argument to that method.
  final Widget? child;

  @override
  State<StretchingOverscrollIndicator> createState() => _StretchingOverscrollIndicatorState();

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(EnumProperty<AxisDirection>('axisDirection', axisDirection));
  }
}

class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndicator> with TickerProviderStateMixin {
  late final _StretchController _stretchController = _StretchController(vsync: this);
  ScrollNotification? _lastNotification;
  OverscrollNotification? _lastOverscrollNotification;
  bool _accepted = true;

  bool _handleScrollNotification(ScrollNotification notification) {
    if (!widget.notificationPredicate(notification))
      return false;

    if (notification is OverscrollNotification) {
      _lastOverscrollNotification = notification;
      if (_lastNotification.runtimeType is! OverscrollNotification) {
        final OverscrollIndicatorNotification confirmationNotification = OverscrollIndicatorNotification(leading: notification.overscroll < 0.0);
        confirmationNotification.dispatch(context);
        _accepted = confirmationNotification._accepted;
      }

      assert(notification.metrics.axis == widget.axis);
      if (_accepted) {
        if (notification.velocity != 0.0) {
          assert(notification.dragDetails == null);
          _stretchController.absorbImpact(notification.velocity.abs());
        } else {
          assert(notification.overscroll != 0.0);
          if (notification.dragDetails != null) {
            _stretchController.pull(notification.overscroll.abs() / notification.metrics.viewportDimension);
          }
        }
      }
    } else if (notification is ScrollEndNotification || notification is ScrollUpdateNotification) {
      _stretchController.scrollEnd();
    }
    _lastNotification = notification;
    return false;
  }

  AlignmentDirectional _getAlignmentForAxisDirection(double overscroll) {
    // Accounts for reversed scrollables by checking the AxisDirection
    switch (widget.axisDirection) {
      case AxisDirection.up:
        return overscroll > 0
            ? AlignmentDirectional.topCenter
            : AlignmentDirectional.bottomCenter;
      case AxisDirection.right:
        return overscroll > 0
            ? AlignmentDirectional.centerEnd
            : AlignmentDirectional.centerStart;
      case AxisDirection.down:
        return overscroll > 0
            ? AlignmentDirectional.bottomCenter
            : AlignmentDirectional.topCenter;
      case AxisDirection.left:
        return overscroll > 0
            ? AlignmentDirectional.centerStart
            : AlignmentDirectional.centerEnd;
    }
  }

  @override
  void dispose() {
    _stretchController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;
    double mainAxisSize;
    return NotificationListener<ScrollNotification>(
      onNotification: _handleScrollNotification,
      child: AnimatedBuilder(
        animation: _stretchController,
        builder: (BuildContext context, Widget? child) {
          final double stretch = _stretchController.value;
          double x = 1.0;
          double y = 1.0;

          switch (widget.axis) {
            case Axis.horizontal:
              x += stretch;
              mainAxisSize = size.width;
              break;
            case Axis.vertical:
              y += stretch;
              mainAxisSize = size.height;
              break;
          }

          final AlignmentDirectional alignment = _getAlignmentForAxisDirection(
            _lastOverscrollNotification?.overscroll ?? 0.0
          );

          final double viewportDimension = _lastOverscrollNotification?.metrics.viewportDimension ?? mainAxisSize;

          final Widget transform = Transform(
            alignment: alignment,
            transform: Matrix4.diagonal3Values(x, y, 1.0),
            child: widget.child,
          );

          // Only clip if the viewport dimension is smaller than that of the
          // screen size in the main axis. If the viewport takes up the whole
          // screen, overflow from transforming the viewport is irrelevant.
          if (stretch != 0.0 && viewportDimension != mainAxisSize) {
            return ClipRect(child: transform);
          }
          return transform;
        },
      ),
    );
  }
}

enum _StretchState {
  idle,
  absorb,
  pull,
  recede,
}

class _StretchController extends ChangeNotifier {
  _StretchController({ required TickerProvider vsync }) {
    _stretchController = AnimationController(vsync: vsync)
      ..addStatusListener(_changePhase);
    final Animation<double> decelerator = CurvedAnimation(
      parent: _stretchController,
      curve: Curves.decelerate,
    )..addListener(notifyListeners);
    _stretchSize = decelerator.drive(_stretchSizeTween);
  }

  late final AnimationController _stretchController;
  late final Animation<double> _stretchSize;
  final Tween<double> _stretchSizeTween = Tween<double>(begin: 0.0, end: 0.0);
  _StretchState _state = _StretchState.idle;
  double _pullDistance = 0.0;

  // Constants from Android.
  static const double _exponentialScalar = math.e / 0.33;
  static const double _stretchIntensity = 0.016;
  static const double _flingFriction = 1.01;
  static const Duration _stretchDuration = Duration(milliseconds: 400);

  double get value => _stretchSize.value;

  /// Handle a fling to the edge of the viewport at a particular velocity.
  ///
  /// The velocity must be positive.
  void absorbImpact(double velocity) {
    assert(velocity >= 0.0);
    velocity = velocity.clamp(1, 10000);
    _stretchSizeTween.begin = _stretchSize.value;
    _stretchSizeTween.end = math.min(_stretchIntensity + (_flingFriction / velocity), 1.0);
    _stretchController.duration = Duration(milliseconds: (velocity * 0.02).round());
    _stretchController.forward(from: 0.0);
    _state = _StretchState.absorb;
  }

  /// Handle a user-driven overscroll.
  ///
  /// The `normalizedOverscroll` argument should be the absolute value of the
  /// scroll distance in logical pixels, divided by the extent of the viewport
  /// in the main axis.
  void pull(double normalizedOverscroll) {
    assert(normalizedOverscroll >= 0.0);
    _pullDistance = normalizedOverscroll + _pullDistance;
    _stretchSizeTween.begin = _stretchSize.value;
    final double linearIntensity =_stretchIntensity * _pullDistance;
    final double exponentialIntensity = _stretchIntensity * (1 - math.exp(-_pullDistance * _exponentialScalar));
    _stretchSizeTween.end = linearIntensity + exponentialIntensity;
    _stretchController.duration = _stretchDuration;
    if (_state != _StretchState.pull) {
      _stretchController.forward(from: 0.0);
      _state = _StretchState.pull;
    } else {
      if (!_stretchController.isAnimating) {
        assert(_stretchController.value == 1.0);
        notifyListeners();
      }
    }
  }

  void scrollEnd() {
    if (_state == _StretchState.pull)
      _recede(_stretchDuration);
  }

  void _changePhase(AnimationStatus status) {
    if (status != AnimationStatus.completed)
      return;
    switch (_state) {
      case _StretchState.absorb:
        _recede(_stretchDuration);
        break;
      case _StretchState.recede:
        _state = _StretchState.idle;
        _pullDistance = 0.0;
        break;
      case _StretchState.pull:
      case _StretchState.idle:
        break;
    }
  }

  void _recede(Duration duration) {
    if (_state == _StretchState.recede || _state == _StretchState.idle)
      return;
    _stretchSizeTween.begin = _stretchSize.value;
    _stretchSizeTween.end = 0.0;
    _stretchController.duration = duration;
    _stretchController.forward(from: 0.0);
    _state = _StretchState.recede;
  }

  @override
  void dispose() {
    _stretchController.dispose();
    super.dispose();
  }
}

/// A notification that either a [GlowingOverscrollIndicator] or a
/// [StretchingOverscrollIndicator] will start showing an overscroll indication.
///
/// To prevent the indicator from showing the indication, call
/// [disallowIndicator] on the notification.
///
/// See also:
///
///  * [GlowingOverscrollIndicator], which generates this type of notification
///    by painting an indicator over the child content.
///  * [StretchingOverscrollIndicator], which generates this type of
///    notification by applying a stretch transformation to the child content.
class OverscrollIndicatorNotification extends Notification with ViewportNotificationMixin {
  /// Creates a notification that an [GlowingOverscrollIndicator] or a
  /// [StretchingOverscrollIndicator] will start showing an overscroll indication.
  ///
  /// The [leading] argument must not be null.
  OverscrollIndicatorNotification({
    required this.leading,
  });

  /// Whether the indication will be shown on the leading edge of the scroll
  /// view.
  final bool leading;

  /// Controls at which offset a [GlowingOverscrollIndicator] draws.
  ///
  /// A positive offset will move the glow away from its edge,
  /// i.e. for a vertical, [leading] indicator, a [paintOffset] of 100.0 will
  /// draw the indicator 100.0 pixels from the top of the edge.
  /// For a vertical indicator with [leading] set to `false`, a [paintOffset]
  /// of 100.0 will draw the indicator 100.0 pixels from the bottom instead.
  ///
  /// A negative [paintOffset] is generally not useful, since the glow will be
  /// clipped.
  ///
  /// This has no effect on a [StretchingOverscrollIndicator].
  double paintOffset = 0.0;

  bool _accepted = true;

  /// Call this method if the glow should be prevented. This method is
  /// deprecated in favor of [disallowIndicator].
  @Deprecated(
    'Use disallowIndicator instead. '
    'This feature was deprecated after v2.5.0-6.0.pre.',
  )
  void disallowGlow() {
    _accepted = false;
  }

  /// Call this method if the overscroll indicator should be prevented.
  void disallowIndicator() {
    _accepted = false;
  }

  @override
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('side: ${leading ? "leading edge" : "trailing edge"}');
  }
}
