// 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/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:macrobenchmarks/common.dart';
import 'package:macrobenchmarks/main.dart' as app;

typedef ControlCallback = Future<void> Function(WidgetController controller);

class ScrollableButtonRoute {
  ScrollableButtonRoute(this.listViewKey, this.buttonKey);

  final String listViewKey;
  final String buttonKey;
}

void macroPerfTestE2E(
  String testName,
  String routeName, {
  Duration? pageDelay,
  Duration duration = const Duration(seconds: 3),
  ControlCallback? body,
  ControlCallback? setup,
}) {
  macroPerfTestMultiPageE2E(
    testName,
    <ScrollableButtonRoute>[
      ScrollableButtonRoute(kScrollableName, routeName),
    ],
    pageDelay: pageDelay,
    duration: duration,
    body: body,
    setup: setup,
  );
}

void macroPerfTestMultiPageE2E(
    String testName,
    List<ScrollableButtonRoute> routes, {
      Duration? pageDelay,
      Duration duration = const Duration(seconds: 3),
      ControlCallback? body,
      ControlCallback? setup,
    }) {
  final WidgetsBinding widgetsBinding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
  assert(widgetsBinding is IntegrationTestWidgetsFlutterBinding);
  final IntegrationTestWidgetsFlutterBinding binding = widgetsBinding as IntegrationTestWidgetsFlutterBinding;
  binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.benchmarkLive;

  testWidgets(testName, (WidgetTester tester) async {
    assert(tester.binding == binding);
    app.main();
    await tester.pumpAndSettle();

    // The slight initial delay avoids starting the timing during a
    // period of increased load on the device. Without this delay, the
    // benchmark has greater noise.
    // See: https://github.com/flutter/flutter/issues/19434
    await tester.binding.delayed(const Duration(microseconds: 250));

    for (final ScrollableButtonRoute route in routes) {
      expect(route.listViewKey, startsWith('/'));
      expect(route.buttonKey, startsWith('/'));

      // Make sure each list view page is settled
      await tester.pumpAndSettle();

      final Finder listView = find.byKey(ValueKey<String>(route.listViewKey));
      // ListView is not a Scrollable, but it contains one
      final Finder scrollable = find.descendant(of: listView, matching: find.byType(Scrollable));
      // scrollable should find one widget as soon as the page is loaded
      expect(scrollable, findsOneWidget);

      final Finder button = find.byKey(ValueKey<String>(route.buttonKey), skipOffstage: false);
      // button may or may not find a widget right away until we scroll to it
      await tester.scrollUntilVisible(button, 50, scrollable: scrollable);
      // After scrolling, button should find one Widget
      expect(button, findsOneWidget);

      // Allow scrolling to settle
      await tester.pumpAndSettle();
      await tester.tap(button);
      // Cannot be pumpAndSettle because some tests have infinite animation.
      await tester.pump(const Duration(milliseconds: 20));
    }

    if (pageDelay != null) {
      // Wait for the page to load
      await tester.binding.delayed(pageDelay);
    }

    if (setup != null) {
      await setup(tester);
    }

    await binding.watchPerformance(() async {
      final Future<void> durationFuture = tester.binding.delayed(duration);
      if (body != null) {
        await body(tester);
      }
      await durationFuture;
    });
  }, semanticsEnabled: false, timeout: Timeout.none);
}
