// 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/material.dart';
import 'package:flutter_test/flutter_test.dart';

bool willPopValue = false;

class SamplePage extends StatefulWidget {
  const SamplePage({ super.key });
  @override
  SamplePageState createState() => SamplePageState();
}

class SamplePageState extends State<SamplePage> {
  ModalRoute<void>? _route;

  Future<bool> _callback() async => willPopValue;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _route?.removeScopedWillPopCallback(_callback);
    _route = ModalRoute.of(context);
    _route?.addScopedWillPopCallback(_callback);
  }

  @override
  void dispose() {
    super.dispose();
    _route?.removeScopedWillPopCallback(_callback);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Sample Page')),
    );
  }
}

int willPopCount = 0;

class SampleForm extends StatelessWidget {
  const SampleForm({ super.key, required this.callback });

  final WillPopCallback callback;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Sample Form')),
      body: SizedBox.expand(
        child: Form(
          onWillPop: () {
            willPopCount += 1;
            return callback();
          },
          child: const TextField(),
        ),
      ),
    );
  }
}

// Expose the protected hasScopedWillPopCallback getter
class _TestPageRoute<T> extends MaterialPageRoute<T> {
  _TestPageRoute({
    super.settings,
    required super.builder,
  }) : super(maintainState: true);

  bool get hasCallback => super.hasScopedWillPopCallback;
}

class _TestPage extends Page<dynamic> {
  _TestPage({
    required this.builder,
    required LocalKey key,
  })  : _key = GlobalKey(),
        super(key: key);

  final WidgetBuilder builder;
  final GlobalKey<dynamic> _key;

  @override
  Route<dynamic> createRoute(BuildContext context) {
    return _TestPageRoute<dynamic>(
        settings: this,
        builder: (BuildContext context) {
          // keep state during move to another location in tree
          return KeyedSubtree(key: _key, child: builder.call(context));
        });
  }
}

void main() {
  testWidgets('ModalRoute scopedWillPopupCallback can inhibit back button', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('Home')),
          body: Builder(
            builder: (BuildContext context) {
              return Center(
                child: TextButton(
                  child: const Text('X'),
                  onPressed: () {
                    showDialog<void>(
                      context: context,
                      builder: (BuildContext context) => const SamplePage(),
                    );
                  },
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(find.byTooltip('Back'), findsNothing);
    expect(find.text('Sample Page'), findsNothing);

    await tester.tap(find.text('X'));
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(find.text('Sample Page'), findsOneWidget);

    willPopValue = false;
    await tester.tap(find.byTooltip('Back'));
    await tester.pump();
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    expect(find.text('Sample Page'), findsOneWidget);

    // Use didPopRoute() to simulate the system back button. Check that
    // didPopRoute() indicates that the notification was handled.
    final dynamic widgetsAppState = tester.state(find.byType(WidgetsApp));
    // ignore: avoid_dynamic_calls
    expect(await widgetsAppState.didPopRoute(), isTrue);
    expect(find.text('Sample Page'), findsOneWidget);

    willPopValue = true;
    await tester.tap(find.byTooltip('Back'));
    await tester.pump();
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    expect(find.text('Sample Page'), findsNothing);
  });

  testWidgets('willPop will only pop if the callback returns true', (WidgetTester tester) async {
    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('Home')),
          body: Builder(
            builder: (BuildContext context) {
              return Center(
                child: TextButton(
                  child: const Text('X'),
                  onPressed: () {
                    Navigator.of(context).push(MaterialPageRoute<void>(
                      builder: (BuildContext context) {
                        return SampleForm(
                          callback: () => Future<bool>.value(willPopValue),
                        );
                      },
                    ));
                  },
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame());
    await tester.tap(find.text('X'));
    await tester.pumpAndSettle();
    expect(find.text('Sample Form'), findsOneWidget);

    // Should pop if callback returns true
    willPopValue = true;
    await tester.tap(find.byTooltip('Back'));
    await tester.pumpAndSettle();
    expect(find.text('Sample Form'), findsNothing);
  });

  testWidgets('Form.willPop can inhibit back button', (WidgetTester tester) async {
    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('Home')),
          body: Builder(
            builder: (BuildContext context) {
              return Center(
                child: TextButton(
                  child: const Text('X'),
                  onPressed: () {
                    Navigator.of(context).push(MaterialPageRoute<void>(
                      builder: (BuildContext context) {
                        return SampleForm(
                          callback: () => Future<bool>.value(willPopValue),
                        );
                      },
                    ));
                  },
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame());

    await tester.tap(find.text('X'));
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(find.text('Sample Form'), findsOneWidget);

    willPopValue = false;
    willPopCount = 0;
    await tester.tap(find.byTooltip('Back'));
    await tester.pump(); // Start the pop "back" operation.
    await tester.pump(); // Complete the willPop() Future.
    await tester.pump(const Duration(seconds: 1)); // Wait until it has finished.
    expect(find.text('Sample Form'), findsOneWidget);
    expect(willPopCount, 1);

    willPopValue = true;
    willPopCount = 0;
    await tester.tap(find.byTooltip('Back'));
    await tester.pump(); // Start the pop "back" operation.
    await tester.pump(); // Complete the willPop() Future.
    await tester.pump(const Duration(seconds: 1)); // Wait until it has finished.
    expect(find.text('Sample Form'), findsNothing);
    expect(willPopCount, 1);
  });

  testWidgets('Form.willPop callbacks do not accumulate', (WidgetTester tester) async {
    Future<bool> showYesNoAlert(BuildContext context) async {
      return (await showDialog<bool>(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            actions: <Widget> [
              TextButton(
                child: const Text('YES'),
                onPressed: () { Navigator.of(context).pop(true); },
              ),
              TextButton(
                child: const Text('NO'),
                onPressed: () { Navigator.of(context).pop(false); },
              ),
            ],
          );
        },
      ))!;
    }

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('Home')),
          body: Builder(
            builder: (BuildContext context) {
              return Center(
                child: TextButton(
                  child: const Text('X'),
                  onPressed: () {
                    Navigator.of(context).push(MaterialPageRoute<void>(
                      builder: (BuildContext context) {
                        return SampleForm(
                          callback: () => showYesNoAlert(context),
                        );
                      },
                    ));
                  },
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame());

    await tester.tap(find.text('X'));
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(find.text('Sample Form'), findsOneWidget);

    // Press the Scaffold's back button. This causes the willPop callback
    // to run, which shows the YES/NO Alert Dialog. Veto the back operation
    // by pressing the Alert's NO button.
    await tester.tap(find.byTooltip('Back'));
    await tester.pump(); // Start the pop "back" operation.
    await tester.pump(); // Call willPop which will show an Alert.
    await tester.tap(find.text('NO'));
    await tester.pump(); // Start the dismiss animation.
    await tester.pump(); // Resolve the willPop callback.
    await tester.pump(const Duration(seconds: 1)); // Wait until it has finished.
    expect(find.text('Sample Form'), findsOneWidget);

    // Do it again.
    // Each time the Alert is shown and dismissed the FormState's
    // didChangeDependencies() method runs. We're making sure that the
    // didChangeDependencies() method doesn't add an extra willPop callback.
    await tester.tap(find.byTooltip('Back'));
    await tester.pump(); // Start the pop "back" operation.
    await tester.pump(); // Call willPop which will show an Alert.
    await tester.tap(find.text('NO'));
    await tester.pump(); // Start the dismiss animation.
    await tester.pump(); // Resolve the willPop callback.
    await tester.pump(const Duration(seconds: 1)); // Wait until it has finished.
    expect(find.text('Sample Form'), findsOneWidget);

    // This time really dismiss the SampleForm by pressing the Alert's
    // YES button.
    await tester.tap(find.byTooltip('Back'));
    await tester.pump(); // Start the pop "back" operation.
    await tester.pump(); // Call willPop which will show an Alert.
    await tester.tap(find.text('YES'));
    await tester.pump(); // Start the dismiss animation.
    await tester.pump(); // Resolve the willPop callback.
    await tester.pump(const Duration(seconds: 1)); // Wait until it has finished.
    expect(find.text('Sample Form'), findsNothing);
  });

  testWidgets('Route.scopedWillPop callbacks do not accumulate', (WidgetTester tester) async {
    late StateSetter contentsSetState; // call this to rebuild the route's SampleForm contents
    bool contentsEmpty = false; // when true, don't include the SampleForm in the route

    final _TestPageRoute<void> route = _TestPageRoute<void>(
      builder: (BuildContext context) {
        return StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            contentsSetState = setState;
            return contentsEmpty ? Container() : SampleForm(key: UniqueKey(), callback: () async => false);
          },
        );
      },
    );

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('Home')),
          body: Builder(
            builder: (BuildContext context) {
              return Center(
                child: TextButton(
                  child: const Text('X'),
                  onPressed: () {
                    Navigator.of(context).push(route);
                  },
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame());

    await tester.tap(find.text('X'));
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(find.text('Sample Form'), findsOneWidget);
    expect(route.hasCallback, isTrue);

    // Rebuild the route's SampleForm child an additional 3x for good measure.
    contentsSetState(() { });
    await tester.pump();
    contentsSetState(() { });
    await tester.pump();
    contentsSetState(() { });
    await tester.pump();

    // Now build the route's contents without the sample form.
    contentsEmpty = true;
    contentsSetState(() { });
    await tester.pump();

    expect(route.hasCallback, isFalse);
  });

  testWidgets('should handle new route if page moved from one navigator to another', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/89133
    late StateSetter contentsSetState;
    bool moveToAnotherNavigator = false;

    final List<Page<dynamic>> pages = <Page<dynamic>>[
      _TestPage(
        key: UniqueKey(),
        builder: (BuildContext context) {
          return WillPopScope(
            onWillPop: () async => true,
            child: const Text('anchor'),
          );
        },
      ),
    ];

    Widget buildNavigator(Key? key, List<Page<dynamic>> pages) {
      return Navigator(
        key: key,
        pages: pages,
        onPopPage: (Route<dynamic> route, dynamic result) {
          return route.didPop(result);
        },
      );
    }

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              contentsSetState = setState;
              if (moveToAnotherNavigator) {
                return buildNavigator(const ValueKey<int>(1), pages);
              }
              return buildNavigator(const ValueKey<int>(2), pages);
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame());
    await tester.pump();
    final _TestPageRoute<dynamic> route1 = ModalRoute.of(tester.element(find.text('anchor')))! as _TestPageRoute<dynamic>;
    expect(route1.hasCallback, isTrue);
    moveToAnotherNavigator = true;
    contentsSetState(() {});

    await tester.pump();
    final _TestPageRoute<dynamic> route2 = ModalRoute.of(tester.element(find.text('anchor')))! as _TestPageRoute<dynamic>;

    expect(route1.hasCallback, isFalse);
    expect(route2.hasCallback, isTrue);
  });
}
