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

void main() {
  final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();

  Finder findPredictiveBackPageTransition() {
    return find.descendant(
      of: find.byType(MaterialApp),
      matching: find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_PredictiveBackPageTransition'),
    );
  }
  Finder findFallbackPageTransition() {
    return find.descendant(
      of: find.byType(MaterialApp),
      matching: find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_ZoomPageTransition'),
    );
  }

  testWidgets('PredictiveBackPageTransitionsBuilder supports predictive back on Android', (WidgetTester tester) async {
    final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
      '/': (BuildContext context) => Material(
        child: TextButton(
          child: const Text('push'),
          onPressed: () { Navigator.of(context).pushNamed('/b'); },
        ),
      ),
      '/b': (BuildContext context) => const Text('page b'),
    };

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          pageTransitionsTheme: PageTransitionsTheme(
            builders: <TargetPlatform, PageTransitionsBuilder>{
              for (final TargetPlatform platform in TargetPlatform.values)
                platform: const PredictiveBackPageTransitionsBuilder(),
            },
          ),
        ),
        routes: routes,
      ),
    );

    expect(find.text('push'), findsOneWidget);
    expect(find.text('page b'), findsNothing);
    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);

    await tester.tap(find.text('push'));
    await tester.pumpAndSettle();

    expect(find.text('push'), findsNothing);
    expect(find.text('page b'), findsOneWidget);
    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);

    // Only Android supports backGesture channel methods. Other platforms will
    // do nothing.
    if (defaultTargetPlatform != TargetPlatform.android) {
      return;
    }

    // Start a system pop gesture, which will switch to using
    // _PredictiveBackPageTransition for the page transition.
    final ByteData startMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'startBackGesture',
        <String, dynamic>{
          'touchOffset': <double>[5.0, 300.0],
          'progress': 0.0,
          'swipeEdge': 0, // left
        },
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      startMessage,
      (ByteData? _) {},
    );
    await tester.pump();

    expect(findPredictiveBackPageTransition(), findsOneWidget);
    expect(findFallbackPageTransition(), findsNothing);
    final Offset startPageBOffset = tester.getTopLeft(find.text('page b'));
    expect(startPageBOffset.dx, 0.0);

    // Drag the system back gesture far enough to commit.
    final ByteData updateMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'updateBackGestureProgress',
        <String, dynamic>{
          'x': 100.0,
          'y': 300.0,
          'progress': 0.35,
          'swipeEdge': 0, // left
        },
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      updateMessage,
      (ByteData? _) {},
    );
    await tester.pumpAndSettle();

    expect(findPredictiveBackPageTransition(), findsNWidgets(2));
    expect(findFallbackPageTransition(), findsNothing);

    final Offset updatePageBOffset = tester.getTopLeft(find.text('page b'));
    expect(updatePageBOffset.dx, greaterThan(startPageBOffset.dx));

    // Commit the system back gesture.
    final ByteData commitMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'commitBackGesture',
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      commitMessage,
      (ByteData? _) {},
    );
    await tester.pumpAndSettle();

    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);
    expect(find.text('push'), findsOneWidget);
    expect(find.text('page b'), findsNothing);
  }, variant: TargetPlatformVariant.all());

  testWidgets('PredictiveBackPageTransitionsBuilder supports canceling a predictive back gesture', (WidgetTester tester) async {
    final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
      '/': (BuildContext context) => Material(
        child: TextButton(
          child: const Text('push'),
          onPressed: () { Navigator.of(context).pushNamed('/b'); },
        ),
      ),
      '/b': (BuildContext context) => const Text('page b'),
    };

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          pageTransitionsTheme: PageTransitionsTheme(
            builders: <TargetPlatform, PageTransitionsBuilder>{
              for (final TargetPlatform platform in TargetPlatform.values)
                platform: const PredictiveBackPageTransitionsBuilder(),
            },
          ),
        ),
        routes: routes,
      ),
    );

    expect(find.text('push'), findsOneWidget);
    expect(find.text('page b'), findsNothing);
    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);

    await tester.tap(find.text('push'));
    await tester.pumpAndSettle();

    expect(find.text('push'), findsNothing);
    expect(find.text('page b'), findsOneWidget);
    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);

    // Only Android supports backGesture channel methods. Other platforms will
    // do nothing.
    if (defaultTargetPlatform != TargetPlatform.android) {
      return;
    }

    // Start a system pop gesture, which will switch to using
    // _PredictiveBackPageTransition for the page transition.
    final ByteData startMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'startBackGesture',
        <String, dynamic>{
          'touchOffset': <double>[5.0, 300.0],
          'progress': 0.0,
          'swipeEdge': 0, // left
        },
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      startMessage,
      (ByteData? _) {},
    );
    await tester.pump();

    expect(findPredictiveBackPageTransition(), findsOneWidget);
    expect(findFallbackPageTransition(), findsNothing);
    final Offset startPageBOffset = tester.getTopLeft(find.text('page b'));
    expect(startPageBOffset.dx, 0.0);

    // Drag the system back gesture.
    final ByteData updateMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'updateBackGestureProgress',
        <String, dynamic>{
          'touchOffset': <double>[100.0, 300.0],
          'progress': 0.35,
          'swipeEdge': 0, // left
        },
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      updateMessage,
      (ByteData? _) {},
    );
    await tester.pumpAndSettle();

    expect(findPredictiveBackPageTransition(), findsNWidgets(2));
    expect(findFallbackPageTransition(), findsNothing);

    final Offset updatePageBOffset = tester.getTopLeft(find.text('page b'));
    expect(updatePageBOffset.dx, greaterThan(startPageBOffset.dx));

    // Cancel the system back gesture.
    final ByteData commitMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'cancelBackGesture',
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      commitMessage,
      (ByteData? _) {},
    );
    await tester.pumpAndSettle();

    expect(find.text('push'), findsNothing);
    expect(find.text('page b'), findsOneWidget);
    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);
  }, variant: TargetPlatformVariant.all());

  testWidgets('if multiple PredictiveBackPageTransitionBuilder observers, only one gets called for a given back gesture', (WidgetTester tester) async {
    bool includingNestedNavigator = false;
    late StateSetter setState;
    final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
      '/': (BuildContext context) => Material(
        child: TextButton(
          child: const Text('push'),
          onPressed: () { Navigator.of(context).pushNamed('/b'); },
        ),
      ),
      '/b': (BuildContext context) => Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          const Text('page b'),
          StatefulBuilder(
            builder: (BuildContext context, StateSetter localSetState) {
              setState = localSetState;
              if (!includingNestedNavigator) {
                return const SizedBox.shrink();
              }
              return Navigator(
                initialRoute: 'b/nested',
                onGenerateRoute: (RouteSettings settings) {
                  WidgetBuilder builder;
                  switch (settings.name) {
                    case 'b/nested':
                      builder = (BuildContext context) => Material(
                        child: Theme(
                          data: ThemeData(
                            pageTransitionsTheme: PageTransitionsTheme(
                              builders: <TargetPlatform, PageTransitionsBuilder>{
                                for (final TargetPlatform platform in TargetPlatform.values)
                                  platform: const PredictiveBackPageTransitionsBuilder(),
                              },
                            ),
                          ),
                          child: const Column(
                            children: <Widget>[
                              Text('Nested route inside of page b'),
                            ],
                          ),
                        ),
                      );
                    default:
                      throw Exception('Invalid route: ${settings.name}');
                  }
                  return MaterialPageRoute<void>(builder: builder, settings: settings);
                },
              );
            },
          ),
        ],
      ),
    };

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          pageTransitionsTheme: PageTransitionsTheme(
            builders: <TargetPlatform, PageTransitionsBuilder>{
              for (final TargetPlatform platform in TargetPlatform.values)
                platform: const PredictiveBackPageTransitionsBuilder(),
            },
          ),
        ),
        routes: routes,
      ),
    );

    expect(find.text('push'), findsOneWidget);
    expect(find.text('page b'), findsNothing);
    expect(find.text('Nested route inside of page b'), findsNothing);
    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);

    await tester.tap(find.text('push'));
    await tester.pumpAndSettle();

    expect(find.text('push'), findsNothing);
    expect(find.text('page b'), findsOneWidget);
    expect(find.text('Nested route inside of page b'), findsNothing);
    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);

    // Only Android supports backGesture channel methods. Other platforms will
    // do nothing.
    if (defaultTargetPlatform != TargetPlatform.android) {
      return;
    }

    // Start a system pop gesture, which will switch to using
    // _PredictiveBackPageTransition for the page transition.
    final ByteData startMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'startBackGesture',
        <String, dynamic>{
          'touchOffset': <double>[5.0, 300.0],
          'progress': 0.0,
          'swipeEdge': 0, // left
        },
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      startMessage,
      (ByteData? _) {},
    );
    await tester.pump();

    expect(findPredictiveBackPageTransition(), findsOneWidget);
    expect(findFallbackPageTransition(), findsNothing);
    final Offset startPageBOffset = tester.getTopLeft(find.text('page b'));
    expect(startPageBOffset.dx, 0.0);

    // Drag the system back gesture.
    final ByteData updateMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'updateBackGestureProgress',
        <String, dynamic>{
          'touchOffset': <double>[100.0, 300.0],
          'progress': 0.3,
          'swipeEdge': 0, // left
        },
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      updateMessage,
      (ByteData? _) {},
    );
    await tester.pumpAndSettle();

    expect(findPredictiveBackPageTransition(), findsNWidgets(2));
    expect(findFallbackPageTransition(), findsNothing);

    final Offset updatePageBOffset = tester.getTopLeft(find.text('page b'));
    expect(updatePageBOffset.dx, greaterThan(startPageBOffset.dx));

    // In the middle of the system back gesture here, add a nested Navigator
    // that includes a new predictive back gesture observer.
    setState(() {
      includingNestedNavigator = true;
    });
    await tester.pumpAndSettle();
    expect(find.text('push'), findsOneWidget);
    expect(find.text('page b'), findsOneWidget);
    expect(find.text('Nested route inside of page b'), findsOneWidget);

    // Send another drag gesture, and ensure that the original observer still
    // gets it.
    final ByteData updateMessage2 = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'updateBackGestureProgress',
        <String, dynamic>{
          'touchOffset': <double>[110.0, 300.0],
          'progress': 0.35,
          'swipeEdge': 0, // left
        },
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      updateMessage2,
      (ByteData? _) {},
    );
    await tester.pumpAndSettle();

    expect(findPredictiveBackPageTransition(), findsNWidgets(2));
    // Despite using a PredictiveBackPageTransitions, the new route has not
    // received a start event, so it is still using the fallback transition.
    expect(findFallbackPageTransition(), findsOneWidget);

    final Offset update2PageBOffset = tester.getTopLeft(find.text('page b'));
    expect(update2PageBOffset.dx, greaterThan(updatePageBOffset.dx));

    // Commit the system back gesture, and the original observer is able to
    // handle the back without interference.
    final ByteData commitMessage = const StandardMethodCodec().encodeMethodCall(
      const MethodCall(
        'commitBackGesture',
      ),
    );
    await binding.defaultBinaryMessenger.handlePlatformMessage(
      'flutter/backgesture',
      commitMessage,
      (ByteData? _) {},
    );
    await tester.pumpAndSettle();

    expect(findPredictiveBackPageTransition(), findsNothing);
    expect(findFallbackPageTransition(), findsOneWidget);
    expect(find.text('push'), findsOneWidget);
    expect(find.text('page b'), findsNothing);
    expect(find.text('Nested route inside of page b'), findsNothing);
  }, variant: TargetPlatformVariant.all());
}
