// 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/foundation.dart';

import 'framework.dart';
import 'navigator.dart';
import 'routes.dart';

/// Manages back navigation gestures.
///
/// The generic type should match or be supertype of the generic type of the
/// enclosing [Route]. If the enclosing Route is a `MaterialPageRoute<int>`,
/// you can define [PopScope] with int or any supertype of int.
///
/// The [canPop] parameter disables back gestures when set to `false`.
///
/// The [onPopInvoked] parameter reports when pop navigation was attempted, and
/// `didPop` indicates whether or not the navigation was successful. The
/// `result` contains the pop result.
///
/// Android has a system back gesture that is a swipe inward from near the edge
/// of the screen. It is recognized by Android before being passed to Flutter.
/// iOS has a similar gesture that is recognized in Flutter by
/// [CupertinoRouteTransitionMixin], not by iOS, and is therefore not a system
/// back gesture.
///
/// If [canPop] is false, then a system back gesture will not pop the route off
/// of the enclosing [Navigator]. [onPopInvoked] will still be called, and
/// `didPop` will be `false`. On iOS when using [CupertinoRouteTransitionMixin]
/// with [canPop] set to false, no gesture will be detected at all, so
/// [onPopInvoked] will not be called. Programmatically attempting pop
/// navigation will also result in a call to [onPopInvoked], with `didPop`
/// indicating success or failure.
///
/// If [canPop] is true, then a system back gesture will cause the enclosing
/// [Navigator] to receive a pop as usual. [onPopInvoked] will be called with
/// `didPop` as true, unless the pop failed for reasons unrelated to
/// [PopScope], in which case it will be false.
///
/// {@tool dartpad}
/// This sample demonstrates showing a confirmation dialog before navigating
/// away from a page.
///
/// ** See code in examples/api/lib/widgets/pop_scope/pop_scope.0.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This sample demonstrates showing how to use PopScope to wrap widget that
/// may pop the page with a result.
///
/// ** See code in examples/api/lib/widgets/pop_scope/pop_scope.1.dart **
/// {@end-tool}
///
/// See also:
///
///  * [NavigatorPopHandler], which is a less verbose way to handle system back
///    gestures in simple cases of nested [Navigator]s.
///  * [Form.canPop] and [Form.onPopInvoked], which can be used to handle system
///    back gestures in the case of a form with unsaved data.
///  * [ModalRoute.registerPopEntry] and [ModalRoute.unregisterPopEntry],
///    which this widget uses to integrate with Flutter's navigation system.
class PopScope<T> extends StatefulWidget {
  /// Creates a widget that registers a callback to veto attempts by the user to
  /// dismiss the enclosing [ModalRoute].
  const PopScope({
    super.key,
    required this.child,
    this.canPop = true,
    this.onPopInvoked,
  });

  /// The widget below this widget in the tree.
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  final Widget child;

  /// {@template flutter.widgets.PopScope.onPopInvoked}
  /// Called after a route pop was handled.
  /// {@endtemplate}
  ///
  /// It's not possible to prevent the pop from happening at the time that this
  /// method is called; the pop has already happened. Use [canPop] to
  /// disable pops in advance.
  ///
  /// This will still be called even when the pop is canceled. A pop is canceled
  /// when the relevant [Route.popDisposition] returns false, such as when
  /// [canPop] is set to false on a [PopScope]. The `didPop` parameter
  /// indicates whether or not the back navigation actually happened
  /// successfully.
  ///
  /// The `result` contains the pop result.
  ///
  /// See also:
  ///
  ///  * [Route.onPopInvoked], which is similar.
  final PopInvokedCallback<T>? onPopInvoked;

  /// {@template flutter.widgets.PopScope.canPop}
  /// When false, blocks the current route from being popped.
  ///
  /// This includes the root route, where upon popping, the Flutter app would
  /// exit.
  ///
  /// If multiple [PopScope] widgets appear in a route's widget subtree, then
  /// each and every `canPop` must be `true` in order for the route to be
  /// able to pop.
  ///
  /// [Android's predictive back](https://developer.android.com/guide/navigation/predictive-back-gesture)
  /// feature will not animate when this boolean is false.
  /// {@endtemplate}
  final bool canPop;

  @override
  State<PopScope<T>> createState() => _PopScopeState<T>();
}

class _PopScopeState<T> extends State<PopScope<T>> implements PopEntry<T> {
  ModalRoute<dynamic>? _route;

  @override
  void onPopInvoked(bool didPop, T? result) {
    widget.onPopInvoked?.call(didPop, result);
  }

  @override
  late final ValueNotifier<bool> canPopNotifier;

  @override
  void initState() {
    super.initState();
    canPopNotifier = ValueNotifier<bool>(widget.canPop);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final ModalRoute<dynamic>? nextRoute = ModalRoute.of(context);
    if (nextRoute != _route) {
      _route?.unregisterPopEntry(this);
      _route = nextRoute;
      _route?.registerPopEntry(this);
    }
  }

  @override
  void didUpdateWidget(PopScope<T> oldWidget) {
    super.didUpdateWidget(oldWidget);
    canPopNotifier.value = widget.canPop;
  }

  @override
  void dispose() {
    _route?.unregisterPopEntry(this);
    canPopNotifier.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => widget.child;
}
