// 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 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

import 'colors.dart';
import 'interface_level.dart';
import 'route.dart';
import 'theme.dart';

// Smoothing factor applied to the device's top padding (which approximates the corner radius)
// to achieve a smoother end to the corner radius animation.  A value of 1.0 would use
// the full top padding. Values less than 1.0 reduce the effective corner radius, improving
// the animation's appearance.  Determined through empirical testing.
const double _kDeviceCornerRadiusSmoothingFactor = 0.9;

// Threshold in logical pixels. If the calculated device corner radius (after applying
// the smoothing factor) is below this value, the corner radius transition animation will
// start from zero. This prevents abrupt transitions for devices with small or negligible
// corner radii.  This value, combined with the smoothing factor, corresponds roughly
// to double the targeted radius of 12.  Determined through testing and visual inspection.
const double _kRoundedDeviceCornersThreshold = 20.0;

// The distance from the top of the open sheet to the top of the screen, as a ratio
// of the total height of the screen. Found from eyeballing a simulator running
// iOS 18.0.
const double _kTopGapRatio = 0.08;

// The minimum distance (i.e., maximum upward stretch) from the top of the sheet
// to the top of the screen, as a ratio of total screen height. This value represents
// how far the sheet can be temporarily pulled upward before snapping back.
// Determined through visual tuning to feel natural on <iPhone16, iPhone 16 Pro>
// running iOS 18.0 simulators.
const double _kStretchedTopGapRatio = 0.072;

// Tween for animating a Cupertino sheet onto the screen.
//
// Begins fully offscreen below the screen and ends onscreen with a small gap at
// the top of the screen. Values found from eyeballing a simulator running iOS 18.0.
final Animatable<Offset> _kBottomUpTween = Tween<Offset>(
  begin: const Offset(0.0, 1.0),
  end: Offset.zero,
);

// Offset change for when a new sheet covers another sheet. '0.0' represents the
// top of the space available for the new sheet, but because the previous sheet
// was lowered slightly, the new sheet needs to go slightly higher than that.
// Values found from eyeballing a simulator running iOS 18.0.
final Animatable<Offset> _kBottomUpTweenWhenCoveringOtherSheet = Tween<Offset>(
  begin: const Offset(0.0, 1.0),
  end: const Offset(0.0, -0.02),
);

// Tween that animates a sheet slightly up when it is covered by a new sheet.
// Values found from eyeballing a simulator running iOS 18.0.
final Animatable<Offset> _kMidUpTween = Tween<Offset>(
  begin: Offset.zero,
  end: const Offset(0.0, -0.005),
);

// Offset from top of screen to slightly down when a fullscreen page is covered
// by a sheet. Values found from eyeballing a simulator running iOS 18.0.
final Animatable<Offset> _kTopDownTween = Tween<Offset>(
  begin: Offset.zero,
  end: const Offset(0.0, 0.07),
);

// Opacity of the overlay color put over the sheet as it moves into the background.
// Used to distinguish the sheet from the background. Value derived from eyeballing
// a simulator running iOS 18.0.
final Animatable<double> _kOpacityTween = Tween<double>(begin: 0.0, end: 0.10);

// The minimum velocity needed for a drag downwards to dismiss the sheet. Eyeballed
// from a comparison against a simulator running iOS 18.0.
const double _kMinFlingVelocity = 2.0; // Screen heights per second.

// The duration for a page to animate when the user releases it mid-swipe. Eyeballed
// from a comparison against a simulator running iOS 18.0.
const Duration _kDroppedSheetDragAnimationDuration = Duration(milliseconds: 300);

// Amount the sheet in the background scales down. Found by measuring the width
// of the sheet in the background and comparing against the screen width on the
// iOS simulator showing an iPhone 16 pro running iOS 18.0. The scale transition
// will go from a default of 1.0 to 1.0 - _kSheetScaleFactor.
const double _kSheetScaleFactor = 0.0835;

final Animatable<double> _kScaleTween = Tween<double>(begin: 1.0, end: 1.0 - _kSheetScaleFactor);

// The signature for a method called on the start of a drag.
typedef _DragStartCallback = void Function();

// The signature for a method called to trigger a change based on a moving drag gesture.
typedef _DragUpdateCallback = void Function(double delta);

// The signature for a method called on the end of a drag, passing the velocity at
// the end of the drag along.
typedef _DragEndCallback = void Function(double velocity);

// The signature for a method that checks if the sheet is currently dragged downwards.
typedef _GetSheetDragged = bool Function();

/// Shows a Cupertino-style sheet widget that slides up from the bottom of the
/// screen and stacks the previous route behind the new sheet.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=5H-WvH5O29I}
///
/// This is a convenience method for displaying [CupertinoSheetRoute] for most
/// use cases. The Widget returned from `scrollableBuilder` will be used to display
/// the content on the [CupertinoSheetRoute]. If the content of the sheet has a
/// scrollable view, the [ScrollController] provided by `scrollableBuilder` can be
/// used to enable the drag-to-dimiss gesture to work with the scrolling of the
/// content. See [CupertinoSheetRoute.scrollableBuilder] for an example.
///
/// `useNestedNavigation` allows new routes to be pushed inside of a [CupertinoSheetRoute]
/// by adding a new [Navigator] inside of the [CupertinoSheetRoute].
///
/// When `useNestedNavigation` is set to `true`, any route pushed to the stack
/// from within the context of the [CupertinoSheetRoute] will display within that
/// sheet. System back gestures and programmatic pops on the initial route in a
/// sheet will also be intercepted to pop the whole [CupertinoSheetRoute]. If
/// a custom [Navigator] setup is needed, like for example to enable named routes
/// or the pages API, then it is recommended to directly push a [CupertinoSheetRoute]
/// to the stack with whatever configuration needed. See [CupertinoSheetRoute] for
/// an example that manually sets up nested navigation.
///
/// The whole sheet can be popped at once by either dragging down on the sheet,
/// or calling [CupertinoSheetRoute.popSheet].
///
/// When `enableDrag` is set to `true` (the default), users can dismiss the sheet
/// by dragging it down or by calling [CupertinoSheetRoute.popSheet]. When
/// `enableDrag` is `false`, users cannot dismiss the sheet by dragging, and it
/// can only be closed by calling [CupertinoSheetRoute.popSheet].
///
/// The `topGap` parameter can be used to customize the gap between the top of
/// the screen and the top of the sheet as a ratio of the screen height.
/// It should be a value between 0.0 and 0.9, where 0.0 means no gap and 0.9
/// means the sheet takes up only the bottom 10% of the screen. If not provided, defaults
/// to 0.08 (8% of screen height).
///
/// When `showDragHandle` is set to `true`, then a drag handle will be placed at
/// the top of the sheet. This flag will default to false.
///
/// iOS sheet widgets are generally designed to be tightly coupled to the context
/// of the widget that opened the sheet. As such, it is not recommended to push
/// a non-sheet route that covers the sheet without first popping the sheet. If
/// necessary however, it can be done by pushing to the root [Navigator].
///
/// If `useNestedNavigation` is `false` (the default), then a [CupertinoSheetRoute]
/// will be shown with no [Navigator] widget. Multiple calls to `showCupertinoSheet`
/// can still be made to show multiple stacked sheets, if desired.
///
/// `showCupertinoSheet` always pushes the [CupertinoSheetRoute] to the root
/// [Navigator]. This is to ensure the previous route animates correctly.
///
/// Returns a [Future] that resolves to the value (if any) that was passed to
/// [Navigator.pop] when the sheet was closed.
///
/// {@tool dartpad}
/// This example shows how to navigate to use [showCupertinoSheet] to display a
/// Cupertino sheet widget with nested navigation.
///
/// ** See code in examples/api/lib/cupertino/sheet/cupertino_sheet.1.dart **
/// {@end-tool}
///
/// See also:
///
///  * [CupertinoSheetRoute] the basic route version of the sheet view.
///  * [showCupertinoDialog] which displays an iOS-styled dialog.
///  * <https://developer.apple.com/design/human-interface-guidelines/sheets>
Future<T?> showCupertinoSheet<T>({
  required BuildContext context,
  @Deprecated(
    'Use scrollableBuilder instead. '
    'This feature was deprecated after v3.33.0-0.2.pre.',
  )
  WidgetBuilder? pageBuilder,
  @Deprecated(
    'Use scrollableBuilder instead. '
    'This feature was deprecated after v3.40.0-0.2.pre.',
  )
  WidgetBuilder? builder,
  ScrollableWidgetBuilder? scrollableBuilder,
  bool useNestedNavigation = false,
  bool enableDrag = true,
  RouteSettings? settings,
  double? topGap,
  bool showDragHandle = false,
}) {
  assert(topGap == null || (topGap >= 0.0 && topGap <= 0.9), 'topGap must be between 0.0 and 0.9');
  assert(pageBuilder != null || builder != null || scrollableBuilder != null);
  assert(
    (pageBuilder == null && builder == null && scrollableBuilder != null) ||
        scrollableBuilder == null,
  );

  final WidgetBuilder? effectiveBuilder = builder ?? pageBuilder;
  final nestedNavigatorKey = GlobalKey<NavigatorState>();
  if (!useNestedNavigation) {
    final PageRoute<T> route = CupertinoSheetRoute<T>(
      builder: effectiveBuilder,
      scrollableBuilder: scrollableBuilder,
      settings: settings,
      enableDrag: enableDrag,
      topGap: topGap,
    );

    return Navigator.of(context, rootNavigator: true).push<T>(route);
  } else {
    Widget nestedNavigationContent(WidgetBuilder builder) {
      return NavigatorPopHandler(
        onPopWithResult: (T? result) {
          nestedNavigatorKey.currentState!.maybePop();
        },
        child: Navigator(
          key: nestedNavigatorKey,
          initialRoute: '/',
          onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) {
            return <Route<void>>[
              CupertinoPageRoute<void>(
                builder: (BuildContext context) {
                  return PopScope(
                    canPop: false,
                    onPopInvokedWithResult: (bool didPop, Object? result) {
                      if (didPop) {
                        return;
                      }
                      Navigator.of(context, rootNavigator: true).pop(result);
                    },
                    child: builder(context),
                  );
                },
              ),
            ];
          },
        ),
      );
    }

    final route = CupertinoSheetRoute<T>(
      scrollableBuilder: (BuildContext context, ScrollController controller) =>
          nestedNavigationContent(
            scrollableBuilder != null
                ? (BuildContext context) => scrollableBuilder(context, controller)
                : effectiveBuilder!,
          ),
      settings: settings,
      enableDrag: enableDrag,
      topGap: topGap,
    );
    return Navigator.of(context, rootNavigator: true).push<T>(route);
  }
}

/// Provides an iOS-style sheet transition.
///
/// The page slides up and stops below the top of the screen. When covered by
/// another sheet view, it will slide slightly up and scale down to appear
/// stacked behind the new sheet.
class CupertinoSheetTransition extends StatefulWidget {
  /// Creates an iOS style sheet transition.
  const CupertinoSheetTransition({
    super.key,
    required this.primaryRouteAnimation,
    required this.secondaryRouteAnimation,
    required this.child,
    required this.linearTransition,
    this.topGap = _kTopGapRatio,
  });

  /// `primaryRouteAnimation` is a linear route animation from 0.0 to 1.0 when
  /// this screen is being pushed.
  final Animation<double> primaryRouteAnimation;

  /// `secondaryRouteAnimation` is a linear route animation from 0.0 to 1.0 when
  /// another screen is being pushed on top of this one.
  final Animation<double> secondaryRouteAnimation;

  /// The widget below this widget in the tree.
  final Widget child;

  /// Whether to perform the transition linearly.
  ///
  /// Used to respond to a drag gesture.
  final bool linearTransition;

  /// The gap between the top of the screen and the top of the sheet as a ratio
  /// of the screen height.
  ///
  ///{@template flutter.cupertino.CupertinoSheetTransition.topGap}
  /// This value should be between 0.0 and 0.9, where 0.0 means no gap (sheet
  /// extends to the top of the screen) and 0.9 means the sheet covers only the
  /// bottom 10% of the screen. A value of 0.08 represents 8% of the screen height.
  ///
  /// If not provided, defaults to a value of 0.08.
  /// {@endtemplate}
  final double topGap;

  /// The primary delegated transition. Will slide a non [CupertinoSheetRoute] page down.
  ///
  /// Provided to the previous route to coordinate transitions between routes.
  ///
  /// If a [CupertinoSheetRoute] already exists in the stack, then it will
  /// slide the previous sheet upwards instead.
  static Widget delegateTransition(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    bool allowSnapshotting,
    Widget? child,
  ) {
    if (CupertinoSheetRoute.hasParentSheet(context)) {
      return _delegatedCoverSheetSecondaryTransition(secondaryAnimation, child);
    }
    final bool linear = Navigator.of(context).userGestureInProgress;

    final Curve curve = linear ? Curves.linear : Curves.linearToEaseOut;
    final Curve reverseCurve = linear ? Curves.linear : Curves.easeInToLinear;
    final curvedAnimation = CurvedAnimation(
      curve: curve,
      reverseCurve: reverseCurve,
      parent: secondaryAnimation,
    );

    final double deviceCornerRadius =
        (MediaQuery.maybeViewPaddingOf(context)?.top ?? 0) * _kDeviceCornerRadiusSmoothingFactor;
    final bool roundedDeviceCorners = deviceCornerRadius > _kRoundedDeviceCornersThreshold;

    final Animatable<BorderRadiusGeometry> decorationTween = Tween<BorderRadiusGeometry>(
      begin: BorderRadius.vertical(
        top: Radius.circular(roundedDeviceCorners ? deviceCornerRadius : 0),
      ),
      end: const BorderRadius.all(Radius.circular(12)),
    );

    final Animation<BorderRadiusGeometry> radiusAnimation = curvedAnimation.drive(decorationTween);
    final Animation<double> opacityAnimation = curvedAnimation.drive(_kOpacityTween);
    final Animation<Offset> slideAnimation = curvedAnimation.drive(_kTopDownTween);
    final Animation<double> scaleAnimation = curvedAnimation.drive(_kScaleTween);
    curvedAnimation.dispose();

    final isDarkMode = CupertinoTheme.brightnessOf(context) == Brightness.dark;
    final overlayColor = isDarkMode ? const Color(0xFFc8c8c8) : const Color(0xFF000000);

    final Widget? contrastedChild = child != null && !secondaryAnimation.isDismissed
        ? Stack(
            children: <Widget>[
              child,
              FadeTransition(
                opacity: opacityAnimation,
                child: ColoredBox(color: overlayColor, child: const SizedBox.expand()),
              ),
            ],
          )
        : child;

    final double topGapHeight = MediaQuery.sizeOf(context).height * _kTopGapRatio;

    return Stack(
      children: <Widget>[
        AnnotatedRegion<SystemUiOverlayStyle>(
          value: const SystemUiOverlayStyle(
            statusBarBrightness: Brightness.dark,
            statusBarIconBrightness: Brightness.light,
          ),
          child: SizedBox(height: topGapHeight, width: double.infinity),
        ),
        SlideTransition(
          position: slideAnimation,
          child: ScaleTransition(
            scale: scaleAnimation,
            filterQuality: FilterQuality.medium,
            alignment: Alignment.topCenter,
            child: AnimatedBuilder(
              animation: radiusAnimation,
              child: child,
              builder: (BuildContext context, Widget? child) {
                return ClipRSuperellipse(
                  borderRadius: !secondaryAnimation.isDismissed
                      ? radiusAnimation.value
                      : BorderRadius.zero,
                  child: contrastedChild,
                );
              },
            ),
          ),
        ),
      ],
    );
  }

  static Widget _delegatedCoverSheetSecondaryTransition(
    Animation<double> secondaryAnimation,
    Widget? child,
  ) {
    const Curve curve = Curves.linearToEaseOut;
    const Curve reverseCurve = Curves.easeInToLinear;
    final curvedAnimation = CurvedAnimation(
      curve: curve,
      reverseCurve: reverseCurve,
      parent: secondaryAnimation,
    );

    final Animation<Offset> slideAnimation = curvedAnimation.drive(_kMidUpTween);
    final Animation<double> scaleAnimation = curvedAnimation.drive(_kScaleTween);
    curvedAnimation.dispose();

    return SlideTransition(
      position: slideAnimation,
      transformHitTests: false,
      child: ScaleTransition(
        scale: scaleAnimation,
        filterQuality: FilterQuality.medium,
        alignment: Alignment.topCenter,
        child: ClipRSuperellipse(
          borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
          child: child,
        ),
      ),
    );
  }

  @override
  State<CupertinoSheetTransition> createState() => _CupertinoSheetTransitionState();
}

class _CupertinoSheetTransitionState extends State<CupertinoSheetTransition>
    with SingleTickerProviderStateMixin {
  // Controls the top padding animation when the sheet is being slightly stretched upward.
  late AnimationController _stretchDragController;

  // Animates the top padding of the sheet based on the _stretchDragController’s value.
  late Animation<double> _stretchDragAnimation;

  // The offset animation when this page is being covered by another sheet.
  late Animation<Offset> _secondaryPositionAnimation;

  // The scale animation when this page is being covered by another sheet.
  late Animation<double> _secondaryScaleAnimation;

  // Curve of primary page which is coming in to cover another route.
  CurvedAnimation? _primaryPositionCurve;

  // Curve of secondary page which is becoming covered by another sheet.
  CurvedAnimation? _secondaryPositionCurve;

  @override
  void initState() {
    super.initState();

    _stretchDragController = AnimationController(
      duration: const Duration(microseconds: 1),
      vsync: this,
    );
    _setupAnimation();
  }

  @override
  void didUpdateWidget(covariant CupertinoSheetTransition oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.primaryRouteAnimation != widget.primaryRouteAnimation ||
        oldWidget.secondaryRouteAnimation != widget.secondaryRouteAnimation) {
      _disposeCurve();
      _setupAnimation();
    }
  }

  @override
  void dispose() {
    _disposeCurve();
    _stretchDragController.dispose();
    super.dispose();
  }

  void _setupAnimation() {
    _primaryPositionCurve = CurvedAnimation(
      curve: Curves.fastEaseInToSlowEaseOut,
      reverseCurve: Curves.fastEaseInToSlowEaseOut.flipped,
      parent: widget.primaryRouteAnimation,
    );
    _secondaryPositionCurve = CurvedAnimation(
      curve: Curves.linearToEaseOut,
      reverseCurve: Curves.easeInToLinear,
      parent: widget.secondaryRouteAnimation,
    );
    // Maintain the same stretch distance (0.008 of screen height) regardless of custom topGap.
    const double stretchDistance = _kTopGapRatio - _kStretchedTopGapRatio;
    final double stretchedTopGap = widget.topGap - stretchDistance;
    _stretchDragAnimation = _stretchDragController.drive(
      Tween<double>(begin: widget.topGap, end: stretchedTopGap),
    );
    _secondaryPositionAnimation = _secondaryPositionCurve!.drive(_kMidUpTween);
    _secondaryScaleAnimation = _secondaryPositionCurve!.drive(_kScaleTween);
  }

  void _disposeCurve() {
    _primaryPositionCurve?.dispose();
    _secondaryPositionCurve?.dispose();
    _primaryPositionCurve = null;
    _secondaryPositionCurve = null;
  }

  Widget _coverSheetPrimaryTransition(
    BuildContext context,
    Animation<double> animation,
    bool linearTransition,
    Widget? child,
  ) {
    final Animatable<Offset> offsetTween = CupertinoSheetRoute.hasParentSheet(context)
        ? _kBottomUpTweenWhenCoveringOtherSheet
        : _kBottomUpTween;

    final curvedAnimation = CurvedAnimation(
      parent: animation,
      curve: linearTransition ? Curves.linear : Curves.fastEaseInToSlowEaseOut,
      reverseCurve: linearTransition ? Curves.linear : Curves.fastEaseInToSlowEaseOut.flipped,
    );

    final Animation<Offset> positionAnimation = curvedAnimation.drive(offsetTween);

    curvedAnimation.dispose();

    return SlideTransition(position: positionAnimation, child: child);
  }

  Widget _coverSheetSecondaryTransition(Animation<double> secondaryAnimation, Widget? child) {
    return SlideTransition(
      position: _secondaryPositionAnimation,
      transformHitTests: false,
      child: ScaleTransition(
        scale: _secondaryScaleAnimation,
        filterQuality: FilterQuality.medium,
        alignment: Alignment.topCenter,
        child: child,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return _StretchDragControllerProvider(
      controller: _stretchDragController,
      child: SizedBox.expand(
        child: AnimatedBuilder(
          animation: _stretchDragAnimation,
          builder: (BuildContext context, Widget? child) {
            return Padding(
              padding: EdgeInsets.only(
                top: MediaQuery.heightOf(context) * _stretchDragAnimation.value,
              ),
              child: _coverSheetSecondaryTransition(
                widget.secondaryRouteAnimation,
                _coverSheetPrimaryTransition(
                  context,
                  widget.primaryRouteAnimation,
                  widget.linearTransition,
                  widget.child,
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

// Internally used to provide the controller for upward stretch animation.
class _StretchDragControllerProvider extends InheritedWidget {
  const _StretchDragControllerProvider({required this.controller, required super.child});

  final AnimationController controller;

  static _StretchDragControllerProvider? maybeOf(BuildContext context) {
    return context.getInheritedWidgetOfExactType<_StretchDragControllerProvider>();
  }

  @override
  bool updateShouldNotify(_StretchDragControllerProvider oldWidget) {
    return false;
  }
}

/// Route for displaying an iOS sheet styled page.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=5H-WvH5O29I}
///
/// The `CupertinoSheetRoute` will slide up from the bottom of the screen and stop
/// below the top of the screen. If the previous route is a non-sheet route, then
/// it will animate downwards to stack behind the new sheet. If the previous route
/// is a sheet route, then it will animate slightly upwards to look like it is laying
/// on top of the previous stack of sheets.
///
/// Typically called by [showCupertinoSheet], which provides some boilerplate for
/// pushing the `CupertinoSheetRoute` to the root navigator and providing simple
/// nested navigation.
///
/// The sheet will be dismissed by dragging downwards on the screen, or a call to
/// [CupertinoSheetRoute.popSheet].
///
/// Any time a CupertinoSheetRoute contains a large scrollable that might conflict
/// with the dismiss drag gesture, pass the provided [ScrollController] from `scrollableBuilder`
/// to the scrollable. A scrollable widget used within the sheet that does not use
/// this [ScrollController] will still scroll in response to user gestures, but
/// the drag to dismiss behavior of the sheet will not trigger. If there is no
/// scrollable area within the sheet, this parameter can be ignored. See below
/// for an example.
///
/// {@tool dartpad}
/// This example shows how to navigate to [CupertinoSheetRoute] by using it the
/// same as a regular route.
///
/// ** See code in examples/api/lib/cupertino/sheet/cupertino_sheet.0.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows how to show a Cupertino Sheet with nested navigation manually
/// set up in order to enable restorable state.
///
/// ** See code in examples/api/lib/cupertino/sheet/cupertino_sheet.2.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows how to show a Cupertino Sheet with scrollable content.
///
/// ** See code in examples/api/lib/cupertino/sheet/cupertino_sheet.3.dart **
/// {@end-tool}
///
/// See also:
///   * [showCupertinoSheet], which is a convenience method for pushing a
///     `CupertinoSheetRoute`, with optional nested navigation built in.
class CupertinoSheetRoute<T> extends PageRoute<T> with _CupertinoSheetRouteTransitionMixin<T> {
  /// Creates a page route that displays an iOS styled sheet.
  CupertinoSheetRoute({
    super.settings,
    @Deprecated(
      'Use scrollableBuilder instead. '
      'This feature was deprecated after v3.40.0-0.2.pre.',
    )
    this.builder,
    this.scrollableBuilder,
    this.enableDrag = true,
    this.showDragHandle = false,
    double? topGap,
  }) : assert(
         topGap == null || (topGap >= 0.0 && topGap <= 0.9),
         'topGap must be between 0.0 and 0.9',
       ),
       assert(
         builder != null || scrollableBuilder != null,
         'Either scrollableBuilder or builder must not be null',
       ),
       _topGap = topGap;

  /// Builds the primary contents of the sheet route.
  @Deprecated(
    'Use scrollableBuilder instead. '
    'This feature was deprecated after v3.40.0-0.2.pre.',
  )
  final WidgetBuilder? builder;

  /// Builds the primary contents of the sheet route with a provided [ScrollController].
  ///
  /// If the scrollable content built by this builder uses the provided [ScrollController],
  /// then when a downward drag is applied to the scrollable area while the content
  /// is scrolled to the top, the drag to dismiss behavior of the sheet will be triggered.
  ///
  /// {@tool dartpad}
  /// This example shows how to show a Cupertino Sheet with scrollable content.
  ///
  /// ** See code in examples/api/lib/cupertino/sheet/cupertino_sheet.3.dart **
  /// {@end-tool}
  final ScrollableWidgetBuilder? scrollableBuilder;

  ScrollableWidgetBuilder get _effectiveBuilder {
    return scrollableBuilder ??
        (BuildContext context, ScrollController controller) => builder!(context);
  }

  @override
  final bool enableDrag;

  // The gap between the top of the screen and the top of the sheet.
  final double? _topGap;

  @override
  double get topGap => _topGap ?? _kTopGapRatio;

  @override
  bool get _hasCustomTopGap => _topGap != null;

  /// Shows a drag handle at the top of the sheet.
  ///
  /// Defaults to false.
  final bool showDragHandle;

  Widget _sheetWithDragHandle(BuildContext context, ScrollController controller) {
    if (!showDragHandle) {
      return _effectiveBuilder(context, controller);
    }

    // Values derived from Apple's Figma files and a simulator running iOS 18.2.
    const dragHandleTopPadding = 5.0;
    const dragHandleHeight = 5.0;
    const dragHandleWidth = 36.0;
    const dragHandlePadding = 15.0;

    return Stack(
      fit: StackFit.expand,
      children: <Widget>[
        MediaQuery(
          data: MediaQuery.of(
            context,
          ).copyWith(padding: const EdgeInsets.only(top: dragHandlePadding)),
          child: _effectiveBuilder(context, controller),
        ),
        const Align(
          alignment: Alignment.topCenter,
          child: Padding(
            padding: EdgeInsetsGeometry.only(top: dragHandleTopPadding),
            child: DecoratedBox(
              decoration: ShapeDecoration(
                shape: RoundedSuperellipseBorder(
                  borderRadius: BorderRadiusGeometry.all(Radius.circular(dragHandleWidth / 2)),
                ),
                color: CupertinoColors.tertiaryLabel,
              ),
              child: SizedBox(height: dragHandleHeight, width: dragHandleWidth),
            ),
          ),
        ),
      ],
    );
  }

  @override
  Widget buildContent(BuildContext context) {
    return MediaQuery.removePadding(
      context: context,
      removeTop: true,
      child: ClipRSuperellipse(
        borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
        child: CupertinoUserInterfaceLevel(
          data: CupertinoUserInterfaceLevelData.elevated,
          child: _CupertinoSheetScope(
            child: _CupertinoDraggableScrollableSheet<T>(
              enabledCallback: () => enableDrag,
              onStartPopGesture: () =>
                  _CupertinoSheetRouteTransitionMixin._startPopGesture<T>(this, topGap),
              builder: _sheetWithDragHandle,
            ),
          ),
        ),
      ),
    );
  }

  /// Checks if a Cupertino sheet view exists in the widget tree above the current
  /// context.
  static bool hasParentSheet(BuildContext context) {
    return _CupertinoSheetScope.maybeOf(context) != null;
  }

  /// Pops the entire [CupertinoSheetRoute], if a sheet route exists in the stack.
  ///
  /// Used if to pop an entire sheet at once, if there is nested navigation within
  /// that sheet.
  static void popSheet(BuildContext context) {
    if (hasParentSheet(context)) {
      Navigator.of(context, rootNavigator: true).pop();
    }
  }

  @override
  Color? get barrierColor => CupertinoColors.transparent;

  @override
  bool get barrierDismissible => false;

  @override
  String? get barrierLabel => null;

  @override
  bool get maintainState => true;

  @override
  bool get opaque => false;
}

// Internally used to see if another sheet is in the tree already.
class _CupertinoSheetScope extends InheritedWidget {
  const _CupertinoSheetScope({required super.child});

  static _CupertinoSheetScope? maybeOf(BuildContext context) {
    return context.getInheritedWidgetOfExactType<_CupertinoSheetScope>();
  }

  @override
  bool updateShouldNotify(_CupertinoSheetScope oldWidget) => false;
}

/// A mixin that replaces the entire screen with an iOS sheet transition for a
/// [PageRoute].
///
/// See also:
///
///  * [CupertinoSheetRoute], which is a [PageRoute] that leverages this mixin.
mixin _CupertinoSheetRouteTransitionMixin<T> on PageRoute<T> {
  /// Builds the primary contents of the route.
  @protected
  Widget buildContent(BuildContext context);

  @override
  Duration get transitionDuration => const Duration(milliseconds: 500);

  @override
  DelegatedTransitionBuilder? get delegatedTransition {
    if (_hasCustomTopGap) {
      return null;
    }
    return CupertinoSheetTransition.delegateTransition;
  }

  /// Determines whether the content can be dragged.
  ///
  /// If `true`, dragging is enabled; otherwise, it remains fixed.
  bool get enableDrag;

  /// The gap between the top of the screen and the top of the sheet as a ratio
  /// of the screen height.
  ///
  /// {@macro flutter.cupertino.CupertinoSheetTransition.topGap}
  double get topGap;

  /// Whether a custom top gap has been set.
  bool get _hasCustomTopGap;

  @override
  Widget buildPage(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
  ) {
    return buildContent(context);
  }

  static _CupertinoDragGestureController<T> _startPopGesture<T>(
    ModalRoute<T> route,
    double topGap,
  ) {
    return _CupertinoDragGestureController<T>(
      topGap: topGap,
      navigator: route.navigator!,
      getIsCurrent: () => route.isCurrent,
      getIsActive: () => route.isActive,
      popDragController: route.controller!, // protected access
    );
  }

  /// Returns a [CupertinoSheetTransition].
  static Widget buildPageTransitions<T>(
    ModalRoute<T> route,
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget child,
    bool enableDrag,
    double topGap,
  ) {
    final bool linearTransition = route.popGestureInProgress;
    return CupertinoSheetTransition(
      primaryRouteAnimation: animation,
      secondaryRouteAnimation: secondaryAnimation,
      linearTransition: linearTransition,
      topGap: topGap,
      child: _CupertinoDragGestureDetector<T>(
        enabledCallback: () => enableDrag,
        onStartPopGesture: () => _startPopGesture<T>(route, topGap),
        child: child,
      ),
    );
  }

  @override
  bool canTransitionFrom(TransitionRoute<dynamic> previousRoute) {
    return !_hasCustomTopGap;
  }

  @override
  bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
    if (this is CupertinoSheetRoute<dynamic> && _hasCustomTopGap) {
      return false;
    }
    return nextRoute is _CupertinoSheetRouteTransitionMixin;
  }

  @override
  Widget buildTransitions(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget child,
  ) {
    return buildPageTransitions<T>(
      this,
      context,
      animation,
      secondaryAnimation,
      child,
      enableDrag,
      topGap,
    );
  }
}

class _CupertinoDragGestureDetector<T> extends StatefulWidget {
  const _CupertinoDragGestureDetector({
    super.key,
    required this.enabledCallback,
    required this.onStartPopGesture,
    required this.child,
  });

  final Widget child;

  final ValueGetter<bool> enabledCallback;

  final ValueGetter<_CupertinoDragGestureController<T>> onStartPopGesture;

  @override
  _CupertinoDragGestureDetectorState<T> createState() => _CupertinoDragGestureDetectorState<T>();
}

class _CupertinoDragGestureDetectorState<T> extends State<_CupertinoDragGestureDetector<T>> {
  _CupertinoDragGestureController<T>? _dragGestureController;

  late VerticalDragGestureRecognizer _recognizer;
  _StretchDragControllerProvider? _stretchDragController;

  static VelocityTracker _cupertinoVelocityBuilder(PointerEvent event) =>
      IOSScrollViewFlingVelocityTracker(event.kind);

  double get sheetHeight => context.size!.height;

  @override
  void initState() {
    super.initState();
    assert(_stretchDragController == null);
    _stretchDragController = _StretchDragControllerProvider.maybeOf(context);
    _recognizer = VerticalDragGestureRecognizer(debugOwner: this)
      ..velocityTrackerBuilder = _cupertinoVelocityBuilder
      ..onStart = _handleDragStart
      ..onUpdate = _handleDragUpdate
      ..onEnd = _handleDragEnd
      ..onCancel = _handleDragCancel;
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _stretchDragController = _StretchDragControllerProvider.maybeOf(context);
  }

  @override
  void dispose() {
    _recognizer.dispose();

    // If this is disposed during a drag, call navigator.didStopUserGesture.
    if (_dragGestureController != null) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (_dragGestureController?.navigator.mounted ?? false) {
          _dragGestureController?.navigator.didStopUserGesture();
        }
        _dragGestureController = null;
      });
    }
    super.dispose();
  }

  void _handleDragStart(DragStartDetails details) {
    assert(mounted);
    assert(_dragGestureController == null);
    _dragGestureController = widget.onStartPopGesture();
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    assert(mounted);
    assert(_dragGestureController != null);
    if (_stretchDragController == null) {
      return;
    }
    final double delta = sheetHeight > 0 ? details.primaryDelta! / sheetHeight : 0.0;
    _dragGestureController!.dragUpdate(
      // Divide by size of the sheet.
      delta,
      _stretchDragController!.controller,
    );
  }

  void _handleDragEnd(DragEndDetails details) {
    assert(mounted);
    assert(_dragGestureController != null);
    if (_stretchDragController == null) {
      _dragGestureController = null;
      return;
    }
    final double velocity = sheetHeight > 0
        ? details.velocity.pixelsPerSecond.dy / sheetHeight
        : 0.0;
    _dragGestureController!.dragEnd(velocity, _stretchDragController!.controller);
    _dragGestureController = null;
  }

  void _handleDragCancel() {
    assert(mounted);
    // This can be called even if start is not called, paired with the "down" event
    // that we don't consider here.
    if (_stretchDragController == null) {
      _dragGestureController = null;
      return;
    }
    _dragGestureController?.dragEnd(0.0, _stretchDragController!.controller);
    _dragGestureController = null;
  }

  void _handlePointerDown(PointerDownEvent event) {
    if (widget.enabledCallback()) {
      _recognizer.addPointer(event);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerDown: _handlePointerDown,
      behavior: HitTestBehavior.translucent,
      child: widget.child,
    );
  }
}

class _CupertinoDragGestureController<T> {
  /// Creates a controller for an iOS-style back gesture.
  _CupertinoDragGestureController({
    required this.navigator,
    required this.popDragController,
    required this.getIsActive,
    required this.getIsCurrent,
    required this.topGap,
  }) {
    navigator.didStartUserGesture();
  }

  final AnimationController popDragController;
  final NavigatorState navigator;
  final ValueGetter<bool> getIsActive;
  final ValueGetter<bool> getIsCurrent;
  final double topGap;

  /// The drag gesture has changed by [delta]. The total range of the drag
  /// should be 0.0 to 1.0.
  void dragUpdate(double delta, AnimationController? upController) {
    if (upController != null &&
        popDragController.value == 1.0 &&
        (upController.value > 0 || delta < 0)) {
      // Divide by stretchable range (when dragging upward at max extent).
      // Maintain the same stretch distance regardless of custom topGap.
      const double stretchDistance = _kTopGapRatio - _kStretchedTopGapRatio;
      upController.value -= delta / stretchDistance;
    } else {
      popDragController.value -= delta;
    }
  }

  bool isDragged() {
    return popDragController.value != 1.0;
  }

  /// The drag gesture has ended with a vertical motion of [velocity] as a
  /// fraction of screen height per second.
  void dragEnd(double velocity, AnimationController? upController) {
    // If the sheet is in a stretched state (dragged upward beyond max size),
    // reverse the stretch to return to the normal max height.
    if (upController != null && upController.value > 0) {
      upController.animateBack(
        0.0,
        duration: const Duration(milliseconds: 180),
        curve: Curves.easeOut,
      );
      navigator.didStopUserGesture();
      return;
    }

    // Fling in the appropriate direction.
    //
    // This curve has been determined through rigorously eyeballing native iOS
    // animations on a simulator running iOS 18.0.
    const Curve animationCurve = Curves.easeOut;
    final bool isCurrent = getIsCurrent();
    final bool animateForward;

    if (!isCurrent) {
      // If the page has already been navigated away from, then the animation
      // direction depends on whether or not it's still in the navigation stack,
      // regardless of velocity or drag position. For example, if a route is
      // being slowly dragged back by just a few pixels, but then a programmatic
      // pop occurs, the route should still be animated off the screen.
      // See https://github.com/flutter/flutter/issues/141268.
      animateForward = getIsActive();
    } else if (velocity.abs() >= _kMinFlingVelocity) {
      // If the user releases the page before mid screen with sufficient velocity,
      // or after mid screen, we should animate the page out. Otherwise, the page
      // should be animated back in.
      animateForward = velocity <= 0;
    } else {
      // If the drag is dropped with low velocity, the sheet will pop if the
      // the drag goes a little past the halfway point on the screen. This is
      // eyeballed on a simulator running iOS 18.0.
      animateForward = popDragController.value > 0.52;
    }

    if (animateForward) {
      popDragController.animateTo(
        1.0,
        duration: _kDroppedSheetDragAnimationDuration,
        curve: animationCurve,
      );
    } else {
      if (isCurrent) {
        // This route is destined to pop at this point. Reuse navigator's pop.
        navigator.pop();
      }

      if (popDragController.isAnimating) {
        popDragController.animateBack(
          0.0,
          duration: _kDroppedSheetDragAnimationDuration,
          curve: animationCurve,
        );
      }
    }

    if (popDragController.isAnimating) {
      // Keep the userGestureInProgress in true state so we don't change the
      // curve of the page transition mid-flight since CupertinoPageTransition
      // depends on userGestureInProgress.
      // late AnimationStatusListener animationStatusCallback;
      void animationStatusCallback(AnimationStatus status) {
        navigator.didStopUserGesture();
        popDragController.removeStatusListener(animationStatusCallback);
      }

      popDragController.addStatusListener(animationStatusCallback);
    } else {
      navigator.didStopUserGesture();
    }
  }
}

class _CupertinoSheetScrollController extends ScrollController {
  _CupertinoSheetScrollController({
    required this.onDragStart,
    required this.onDragUpdate,
    required this.onDragEnd,
    required this.sheetIsDraggedDown,
  });

  final _DragStartCallback onDragStart;
  final _DragEndCallback onDragUpdate;
  final _DragUpdateCallback onDragEnd;
  final _GetSheetDragged sheetIsDraggedDown;

  @override
  _CupertinoSheetScrollPosition createScrollPosition(
    ScrollPhysics physics,
    ScrollContext context,
    ScrollPosition? oldPosition,
  ) {
    return _CupertinoSheetScrollPosition(
      physics: physics.applyTo(const AlwaysScrollableScrollPhysics()),
      context: context,
      oldPosition: oldPosition,
      onDragStart: onDragStart,
      onDragUpdate: onDragUpdate,
      onDragEnd: onDragEnd,
      sheetIsDraggedDown: sheetIsDraggedDown,
    );
  }
}

/// A scroll position that manages scroll activities for
/// [_CupertinoSheetScrollController].
///
/// This class is a concrete subclass of [ScrollPosition] logic that handles a
/// single [ScrollContext], such as a [Scrollable]. An instance of this class
/// manages [ScrollActivity] instances, which in response to user gestures either
/// changes the visible content offset in the [Scrollable]'s [Viewport], or reports
/// the delta change or velocity of the user's gestures back to
/// [_CupertinoDragGestureController] through [_CupertinoSheetScrollController].
class _CupertinoSheetScrollPosition extends ScrollPositionWithSingleContext {
  // This class is modified version of _DraggableScrollableSheetScrollPosition
  // from DraggableScrollableSheet. If a change needs to be made to this, check and
  // see if the original class needs the change as well.
  _CupertinoSheetScrollPosition({
    required super.physics,
    required super.context,
    super.oldPosition,
    required this.onDragStart,
    required this.onDragUpdate,
    required this.onDragEnd,
    required this.sheetIsDraggedDown,
  });

  VoidCallback? _dragCancelCallback;
  final Set<AnimationController> _ballisticControllers = <AnimationController>{};
  bool get listShouldScroll => pixels > 0.0;

  final _DragStartCallback onDragStart;
  final _DragEndCallback onDragUpdate;
  final _DragUpdateCallback onDragEnd;

  final _GetSheetDragged sheetIsDraggedDown;

  @override
  void absorb(ScrollPosition other) {
    super.absorb(other);
    assert(_dragCancelCallback == null);

    if (other is! _CupertinoSheetScrollPosition) {
      return;
    }

    if (other._dragCancelCallback != null) {
      _dragCancelCallback = other._dragCancelCallback;
      other._dragCancelCallback = null;
    }
  }

  @override
  void beginActivity(ScrollActivity? newActivity) {
    // Cancel the running ballistic simulations
    for (final AnimationController ballisticController in _ballisticControllers) {
      ballisticController.stop();
    }
    super.beginActivity(newActivity);
  }

  @override
  void dispose() {
    for (final AnimationController ballisticController in _ballisticControllers) {
      ballisticController.dispose();
    }
    _ballisticControllers.clear();
    super.dispose();
  }

  @override
  void applyUserOffset(double delta) {
    onDragStart();
    if (!listShouldScroll && (delta > 0 || sheetIsDraggedDown())) {
      onDragUpdate(delta);
    } else {
      super.applyUserOffset(delta);
    }
  }

  @override
  void goBallistic(double velocity) {
    // End drag gesture.
    if ((velocity == 0.0) ||
        (velocity < 0.0 && listShouldScroll) ||
        (velocity > 0.0 && pixels != maxScrollExtent)) {
      onDragEnd(0.0);
      super.goBallistic(velocity);
      return;
    }
    _dragCancelCallback?.call();
    _dragCancelCallback = null;
    if (velocity < 0.0 && !listShouldScroll) {
      onDragEnd(velocity);
      super.goBallistic(0);
      return;
    }
    onDragEnd(0.0);
    super.goBallistic(velocity);
  }

  @override
  Drag drag(DragStartDetails details, VoidCallback dragCancelCallback) {
    // Save this so we can call it later if we have to [goBallistic] on our own.
    _dragCancelCallback = dragCancelCallback;
    return super.drag(details, dragCancelCallback);
  }
}

class _CupertinoDraggableScrollableSheet<T> extends StatefulWidget {
  const _CupertinoDraggableScrollableSheet({
    super.key,
    required this.enabledCallback,
    required this.onStartPopGesture,
    required this.builder,
  });

  final ScrollableWidgetBuilder builder;

  final ValueGetter<bool> enabledCallback;

  final ValueGetter<_CupertinoDragGestureController<T>> onStartPopGesture;

  @override
  _CupertinoDraggableScrollableSheetState<T> createState() =>
      _CupertinoDraggableScrollableSheetState<T>();
}

class _CupertinoDraggableScrollableSheetState<T>
    extends State<_CupertinoDraggableScrollableSheet<T>> {
  late _CupertinoSheetScrollController _scrollController;
  _CupertinoDragGestureController<T>? _dragGestureController;

  @override
  void initState() {
    super.initState();
    _scrollController = _CupertinoSheetScrollController(
      onDragStart: _dragStart,
      onDragUpdate: _dragUpdate,
      onDragEnd: _handleDragEnd,
      sheetIsDraggedDown: () => _dragGestureController?.isDragged() ?? false,
    );
  }

  @override
  void dispose() {
    // If this is disposed during a drag, call navigator.didStopUserGesture.
    if (_dragGestureController != null) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (_dragGestureController?.navigator.mounted ?? false) {
          _dragGestureController?.navigator.didStopUserGesture();
        }
        _dragGestureController = null;
      });
    }
    _scrollController.dispose();
    super.dispose();
  }

  void _dragStart() {
    assert(mounted);
    _dragGestureController ??= widget.onStartPopGesture();
  }

  void _dragUpdate(double delta) {
    assert(mounted);
    if (_dragGestureController != null) {
      _dragGestureController!.dragUpdate(
        delta / (context.size!.height - (context.size!.height * _kTopGapRatio)),
        null,
      );
    }
  }

  void _handleDragEnd(double velocity) {
    assert(mounted);
    if (_dragGestureController != null) {
      _dragGestureController!.dragEnd(-velocity / context.size!.height, null);
      _dragGestureController = null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(context, _scrollController);
  }
}
