// 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';

class TestIntent extends Intent {
  const TestIntent();
}

class TestAction extends Action<Intent> {
  TestAction();

  static const LocalKey key = ValueKey<Type>(TestAction);

  int calls = 0;

  @override
  void invoke(Intent intent) {
    calls += 1;
  }
}

void main() {
  testWidgets('WidgetsApp with builder only', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(
      WidgetsApp(
        key: key,
        builder: (BuildContext context, Widget? child) {
          return const Placeholder();
        },
        color: const Color(0xFF123456),
      ),
    );
    expect(find.byKey(key), findsOneWidget);
  });

  testWidgets('WidgetsApp default key bindings', (WidgetTester tester) async {
    bool? checked = false;
    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(
      WidgetsApp(
        key: key,
        builder: (BuildContext context, Widget? child) {
          return Material(
            child: Checkbox(
              value: checked,
              autofocus: true,
              onChanged: (bool? value) {
                checked = value;
              },
            ),
          );
        },
        color: const Color(0xFF123456),
      ),
    );
    await tester.pump(); // Wait for focus to take effect.
    await tester.sendKeyEvent(LogicalKeyboardKey.space);
    await tester.pumpAndSettle();
    // Default key mapping worked.
    expect(checked, isTrue);
  });

  testWidgets('WidgetsApp can override default key bindings', (WidgetTester tester) async {
    final TestAction action = TestAction();
    bool? checked = false;
    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(
      WidgetsApp(
        key: key,
        actions: <Type, Action<Intent>>{
          TestIntent: action,
        },
        shortcuts: const <ShortcutActivator, Intent> {
          SingleActivator(LogicalKeyboardKey.space): TestIntent(),
        },
        builder: (BuildContext context, Widget? child) {
          return Material(
            child: Checkbox(
              value: checked,
              autofocus: true,
              onChanged: (bool? value) {
                checked = value;
              },
            ),
          );
        },
        color: const Color(0xFF123456),
      ),
    );
    await tester.pump();

    await tester.sendKeyEvent(LogicalKeyboardKey.space);
    await tester.pumpAndSettle();
    // Default key mapping was not invoked.
    expect(checked, isFalse);
    // Overridden mapping was invoked.
    expect(action.calls, equals(1));
  });

  testWidgets('WidgetsApp default activation key mappings work', (WidgetTester tester) async {
    bool? checked = false;

    await tester.pumpWidget(
      WidgetsApp(
        builder: (BuildContext context, Widget? child) {
          return Material(
            child: Checkbox(
              value: checked,
              autofocus: true,
              onChanged: (bool? value) {
                checked = value;
              },
            ),
          );
        },
        color: const Color(0xFF123456),
      ),
    );
    await tester.pump();

    // Test three default buttons for the activation action.
    await tester.sendKeyEvent(LogicalKeyboardKey.space);
    await tester.pumpAndSettle();
    expect(checked, isTrue);

    // Only space is used as an activation key on web.
    if (kIsWeb) {
      return;
    }

    checked = false;
    await tester.sendKeyEvent(LogicalKeyboardKey.enter);
    await tester.pumpAndSettle();
    expect(checked, isTrue);

    checked = false;
    await tester.sendKeyEvent(LogicalKeyboardKey.numpadEnter);
    await tester.pumpAndSettle();
    expect(checked, isTrue);

    checked = false;
    await tester.sendKeyEvent(LogicalKeyboardKey.gameButtonA);
    await tester.pumpAndSettle();
    expect(checked, isTrue);
  }, variant: KeySimulatorTransitModeVariant.all());

  group('error control test', () {
    Future<void> expectFlutterError({
      required GlobalKey<NavigatorState> key,
      required Widget widget,
      required WidgetTester tester,
      required String errorMessage,
    }) async {
      await tester.pumpWidget(widget);
      late FlutterError error;
      try {
        key.currentState!.pushNamed('/path');
      } on FlutterError catch (e) {
        error = e;
      } finally {
        expect(error, isNotNull);
        expect(error, isFlutterError);
        expect(error.toStringDeep(), errorMessage);
      }
    }

    testWidgets('push unknown route when onUnknownRoute is null', (WidgetTester tester) async {
      final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
      expectFlutterError(
        key: key,
        tester: tester,
        widget: MaterialApp(
          navigatorKey: key,
          home: Container(),
          onGenerateRoute: (_) => null,
        ),
        errorMessage:
          'FlutterError\n'
          '   Could not find a generator for route RouteSettings("/path", null)\n'
          '   in the _WidgetsAppState.\n'
          '   Make sure your root app widget has provided a way to generate\n'
          '   this route.\n'
          '   Generators for routes are searched for in the following order:\n'
          '    1. For the "/" route, the "home" property, if non-null, is used.\n'
          '    2. Otherwise, the "routes" table is used, if it has an entry for\n'
          '   the route.\n'
          '    3. Otherwise, onGenerateRoute is called. It should return a\n'
          '   non-null value for any valid route not handled by "home" and\n'
          '   "routes".\n'
          '    4. Finally if all else fails onUnknownRoute is called.\n'
          '   Unfortunately, onUnknownRoute was not set.\n',
      );
    });

    testWidgets('push unknown route when onUnknownRoute returns null', (WidgetTester tester) async {
      final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
      expectFlutterError(
        key: key,
        tester: tester,
        widget: MaterialApp(
          navigatorKey: key,
          home: Container(),
          onGenerateRoute: (_) => null,
          onUnknownRoute: (_) => null,
        ),
        errorMessage:
          'FlutterError\n'
          '   The onUnknownRoute callback returned null.\n'
          '   When the _WidgetsAppState requested the route\n'
          '   RouteSettings("/path", null) from its onUnknownRoute callback,\n'
          '   the callback returned null. Such callbacks must never return\n'
          '   null.\n' ,
      );
    });
  });

  testWidgets('WidgetsApp can customize initial routes', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    await tester.pumpWidget(
      WidgetsApp(
        navigatorKey: navigatorKey,
        onGenerateInitialRoutes: (String initialRoute) {
          expect(initialRoute, '/abc');
          return <Route<void>>[
            PageRouteBuilder<void>(
              pageBuilder: (
                BuildContext context,
                Animation<double> animation,
                Animation<double> secondaryAnimation,
              ) {
                return const Text('non-regular page one');
              },
            ),
            PageRouteBuilder<void>(
              pageBuilder: (
                BuildContext context,
                Animation<double> animation,
                Animation<double> secondaryAnimation,
              ) {
                return const Text('non-regular page two');
              },
            ),
          ];
        },
        initialRoute: '/abc',
        onGenerateRoute: (RouteSettings settings) {
          return PageRouteBuilder<void>(
            pageBuilder: (
              BuildContext context,
              Animation<double> animation,
              Animation<double> secondaryAnimation,
            ) {
              return const Text('regular page');
            },
          );
        },
        color: const Color(0xFF123456),
      ),
    );
    expect(find.text('non-regular page two'), findsOneWidget);
    expect(find.text('non-regular page one'), findsNothing);
    expect(find.text('regular page'), findsNothing);
    navigatorKey.currentState!.pop();
    await tester.pumpAndSettle();
    expect(find.text('non-regular page two'), findsNothing);
    expect(find.text('non-regular page one'), findsOneWidget);
    expect(find.text('regular page'), findsNothing);
  });

  testWidgets('WidgetsApp.router works', (WidgetTester tester) async {
    final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
      initialRouteInformation: const RouteInformation(
        location: 'initial',
      ),
    );
    final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
      builder: (BuildContext context, RouteInformation information) {
        return Text(information.location!);
      },
      onPopPage: (Route<void> route, void result, SimpleNavigatorRouterDelegate delegate) {
        delegate.routeInformation = const RouteInformation(
          location: 'popped',
        );
        return route.didPop(result);
      },
    );
    await tester.pumpWidget(WidgetsApp.router(
      routeInformationProvider: provider,
      routeInformationParser: SimpleRouteInformationParser(),
      routerDelegate: delegate,
      color: const Color(0xFF123456),
    ));
    expect(find.text('initial'), findsOneWidget);

    // Simulate android back button intent.
    final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute'));
    await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
    await tester.pumpAndSettle();
    expect(find.text('popped'), findsOneWidget);
  });

  testWidgets('WidgetsApp.router has correct default', (WidgetTester tester) async {
    final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
      builder: (BuildContext context, RouteInformation information) {
        return Text(information.location!);
      },
      onPopPage: (Route<Object?> route, Object? result, SimpleNavigatorRouterDelegate delegate) => true,
    );
    await tester.pumpWidget(WidgetsApp.router(
      routeInformationParser: SimpleRouteInformationParser(),
      routerDelegate: delegate,
      color: const Color(0xFF123456),
    ));
    expect(find.text('/'), findsOneWidget);
  });

  testWidgets('WidgetsApp has correct default ScrollBehavior', (WidgetTester tester) async {
    late BuildContext capturedContext;
    await tester.pumpWidget(
      WidgetsApp(
        builder: (BuildContext context, Widget? child) {
          capturedContext = context;
          return const Placeholder();
        },
        color: const Color(0xFF123456),
      ),
    );
    expect(ScrollConfiguration.of(capturedContext).runtimeType, ScrollBehavior);
  });

  test('basicLocaleListResolution', () {
    // Matches exactly for language code.
    expect(
      basicLocaleListResolution(
        <Locale>[
          const Locale('zh'),
          const Locale('un'),
          const Locale('en'),
        ],
        <Locale>[
          const Locale('en'),
        ],
      ),
      const Locale('en'),
    );

    // Matches exactly for language code and country code.
    expect(
      basicLocaleListResolution(
        <Locale>[
          const Locale('en'),
          const Locale('en', 'US'),
        ],
        <Locale>[
          const Locale('en', 'US'),
        ],
      ),
      const Locale('en', 'US'),
    );

    // Matches language+script over language+country
    expect(
      basicLocaleListResolution(
        <Locale>[
          const Locale.fromSubtags(
            languageCode: 'zh',
            scriptCode: 'Hant',
            countryCode: 'HK',
          ),
        ],
        <Locale>[
          const Locale.fromSubtags(
            languageCode: 'zh',
            countryCode: 'HK',
          ),
          const Locale.fromSubtags(
            languageCode: 'zh',
            scriptCode: 'Hant',
          ),
        ],
      ),
      const Locale.fromSubtags(
        languageCode: 'zh',
        scriptCode: 'Hant',
      ),
    );

    // Matches exactly for language code, script code and country code.
    expect(
      basicLocaleListResolution(
        <Locale>[
          const Locale.fromSubtags(
            languageCode: 'zh',
          ),
          const Locale.fromSubtags(
            languageCode: 'zh',
            scriptCode: 'Hant',
            countryCode: 'TW',
          ),
        ],
        <Locale>[
          const Locale.fromSubtags(
            languageCode: 'zh',
            scriptCode: 'Hant',
            countryCode: 'TW',
          ),
        ],
      ),
      const Locale.fromSubtags(
        languageCode: 'zh',
        scriptCode: 'Hant',
        countryCode: 'TW',
      ),
    );

    // Selects for country code if the language code is not found in the
    // preferred locales list.
    expect(
      basicLocaleListResolution(
        <Locale>[
          const Locale.fromSubtags(
            languageCode: 'en',
          ),
          const Locale.fromSubtags(
            languageCode: 'ar',
            countryCode: 'tn',
          ),
        ],
        <Locale>[
          const Locale.fromSubtags(
            languageCode: 'fr',
            countryCode: 'tn',
          ),
        ],
      ),
      const Locale.fromSubtags(
        languageCode: 'fr',
        countryCode: 'tn',
      ),
    );

    // Selects first (default) locale when no match at all is found.
    expect(
      basicLocaleListResolution(
        <Locale>[
          const Locale('tn'),
        ],
        <Locale>[
          const Locale('zh'),
          const Locale('un'),
          const Locale('en'),
        ],
      ),
      const Locale('zh'),
    );
  });

  testWidgets("WidgetsApp reports an exception if the selected locale isn't supported", (WidgetTester tester) async {
    late final List<Locale>? localesArg;
    late final Iterable<Locale> supportedLocalesArg;
    await tester.pumpWidget(
      MaterialApp( // This uses a MaterialApp because it introduces some actual localizations.
        localeListResolutionCallback: (List<Locale>? locales, Iterable<Locale> supportedLocales) {
          localesArg = locales;
          supportedLocalesArg = supportedLocales;
          return const Locale('C_UTF-8');
        },
        builder: (BuildContext context, Widget? child) => const Placeholder(),
        color: const Color(0xFF000000),
      ),
    );
    if (!kIsWeb) {
      // On web, `flutter test` does not guarantee a particular locale, but
      // when using `flutter_tester`, we guarantee that it's en-US, zh-CN.
      // https://github.com/flutter/flutter/issues/93290
      expect(localesArg, const <Locale>[Locale('en', 'US'), Locale('zh', 'CN')]);
    }
    expect(supportedLocalesArg, const <Locale>[Locale('en', 'US')]);
    expect(tester.takeException(), "Warning: This application's locale, C_UTF-8, is not supported by all of its localization delegates.");
  });

  testWidgets('WidgetsApp creates a MediaQuery if `useInheritedMediaQuery` is set to false', (WidgetTester tester) async {
    late BuildContext capturedContext;
    await tester.pumpWidget(
      WidgetsApp(
        builder: (BuildContext context, Widget? child) {
          capturedContext = context;
          return const Placeholder();
        },
        color: const Color(0xFF123456),
      ),
    );
    expect(MediaQuery.of(capturedContext), isNotNull);
  });

  testWidgets('WidgetsApp does not create MediaQuery if `useInheritedMediaQuery` is set to true and one is available', (WidgetTester tester) async {
    late BuildContext capturedContext;
    final UniqueKey uniqueKey = UniqueKey();
    await tester.pumpWidget(
      MediaQuery(
      key: uniqueKey,
        data: const MediaQueryData(),
        child: WidgetsApp(
          useInheritedMediaQuery: true,
          builder: (BuildContext context, Widget? child) {
            capturedContext = context;
            return const Placeholder();
          },
          color: const Color(0xFF123456),
        ),
      ),
    );
    expect(capturedContext.dependOnInheritedWidgetOfExactType<MediaQuery>()?.key, uniqueKey);
  });

  testWidgets('WidgetsApp does create a MediaQuery if `useInheritedMediaQuery` is set to true and none is available', (WidgetTester tester) async {
    late BuildContext capturedContext;
    await tester.pumpWidget(
      WidgetsApp(
        useInheritedMediaQuery: true,
        builder: (BuildContext context, Widget? child) {
          capturedContext = context;
          return const Placeholder();
        },
        color: const Color(0xFF123456),
      ),
    );
    expect(MediaQuery.of(capturedContext), isNotNull);
  });
}

typedef SimpleRouterDelegateBuilder = Widget Function(BuildContext, RouteInformation);
typedef SimpleNavigatorRouterDelegatePopPage<T> = bool Function(Route<T> route, T result, SimpleNavigatorRouterDelegate delegate);

class SimpleRouteInformationParser extends RouteInformationParser<RouteInformation> {
  SimpleRouteInformationParser();

  @override
  Future<RouteInformation> parseRouteInformation(RouteInformation information) {
    return SynchronousFuture<RouteInformation>(information);
  }

  @override
  RouteInformation restoreRouteInformation(RouteInformation configuration) {
    return configuration;
  }
}

class SimpleNavigatorRouterDelegate extends RouterDelegate<RouteInformation> with PopNavigatorRouterDelegateMixin<RouteInformation>, ChangeNotifier {
  SimpleNavigatorRouterDelegate({
    required this.builder,
    required this.onPopPage,
  });

  @override
  GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

  RouteInformation get routeInformation => _routeInformation;
  late RouteInformation _routeInformation;
  set routeInformation(RouteInformation newValue) {
    _routeInformation = newValue;
    notifyListeners();
  }

  final SimpleRouterDelegateBuilder builder;
  final SimpleNavigatorRouterDelegatePopPage<void> onPopPage;

  @override
  Future<void> setNewRoutePath(RouteInformation configuration) {
    _routeInformation = configuration;
    return SynchronousFuture<void>(null);
  }

  bool _handlePopPage(Route<void> route, void data) {
    return onPopPage(route, data, this);
  }

  @override
  Widget build(BuildContext context) {
    return Navigator(
      key: navigatorKey,
      onPopPage: _handlePopPage,
      pages: <Page<void>>[
        // We need at least two pages for the pop to propagate through.
        // Otherwise, the navigator will bubble the pop to the system navigator.
        const MaterialPage<void>(
          child: Text('base'),
        ),
        MaterialPage<void>(
          key: ValueKey<String>(routeInformation.location!),
          child: builder(context, routeInformation),
        ),
      ],
    );
  }
}
