// 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.

// ATTENTION!
//
// This file is not named "*_test.dart", and as such will not run when you run
// "flutter test". It is only intended to be run as part of the
// flutter_gallery_instrumentation_test devicelab test.

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart' show kPrimaryButton;
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gallery/gallery/app.dart' show GalleryApp;
import 'package:flutter_gallery/gallery/demos.dart';
import 'package:flutter_test/flutter_test.dart';

// Reports success or failure to the native code.
const MethodChannel _kTestChannel = MethodChannel('io.flutter.demo.gallery/TestLifecycleListener');

// We don't want to wait for animations to complete before tapping the
// back button in the demos with these titles.
const List<String> _kUnsynchronizedDemoTitles = <String>[
  'Progress indicators',
  'Activity Indicator',
  'Video',
];

// These demos can't be backed out of by tapping a button whose
// tooltip is 'Back'.
const List<String> _kSkippedDemoTitles = <String>[
  'Progress indicators',
  'Activity Indicator',
  'Video',
];

// There are 3 places where the Gallery demos are traversed.
// 1- In widget tests such as dev/integration_tests/flutter_gallery/test/smoke_test.dart
// 2- In driver tests such as dev/integration_tests/flutter_gallery/test_driver/transitions_perf_test.dart
// 3- In on-device instrumentation tests such as dev/integration_tests/flutter_gallery/test/live_smoketest.dart
//
// If you change navigation behavior in the Gallery or in the framework, make
// sure all 3 are covered.

Future<void> main() async {
  try {
    // Verify that _kUnsynchronizedDemos and _kSkippedDemos identify
    // demos that actually exist.
    final List<String> allDemoTitles = kAllGalleryDemos.map((GalleryDemo demo) => demo.title).toList();
    if (!Set<String>.from(allDemoTitles).containsAll(_kUnsynchronizedDemoTitles))
      fail('Unrecognized demo titles in _kUnsynchronizedDemosTitles: $_kUnsynchronizedDemoTitles');
    if (!Set<String>.from(allDemoTitles).containsAll(_kSkippedDemoTitles))
      fail('Unrecognized demo names in _kSkippedDemoTitles: $_kSkippedDemoTitles');

    print('Starting app...');
    runApp(const GalleryApp(testMode: true));
    final _LiveWidgetController controller = _LiveWidgetController(WidgetsBinding.instance);
    for (final GalleryDemoCategory category in kAllGalleryDemoCategories) {
      print('Tapping "${category.name}" section...');
      await controller.tap(find.text(category.name));
      for (final GalleryDemo demo in kGalleryCategoryToDemos[category]!) {
        final Finder demoItem = find.text(demo.title);
        print('Scrolling to "${demo.title}"...');
        await controller.scrollIntoView(demoItem, alignment: 0.5);
        if (_kSkippedDemoTitles.contains(demo.title))
          continue;
        for (int i = 0; i < 2; i += 1) {
          print('Tapping "${demo.title}"...');
          await controller.tap(demoItem); // Launch the demo
          controller.frameSync = !_kUnsynchronizedDemoTitles.contains(demo.title);
          print('Going back to demo list...');
          await controller.tap(backFinder);
          controller.frameSync = true;
        }
      }
      print('Going back to home screen...');
      await controller.tap(find.byTooltip('Back'));
    }
    print('Finished successfully!');
    _kTestChannel.invokeMethod<void>('success');
  } catch (error, stack) {
    print('Caught error: $error\n$stack');
    _kTestChannel.invokeMethod<void>('failure');
  }
}

final Finder backFinder = find.byElementPredicate(
  (Element element) {
    final Widget widget = element.widget;
    if (widget is Tooltip)
      return widget.message == 'Back';
    if (widget is CupertinoNavigationBarBackButton)
      return true;
    return false;
  },
  description: 'Material or Cupertino back button',
);

class _LiveWidgetController extends LiveWidgetController {
  _LiveWidgetController(super.binding);

  /// With [frameSync] enabled, Flutter Driver will wait to perform an action
  /// until there are no pending frames in the app under test.
  bool frameSync = true;

  /// Waits until at the end of a frame the provided [condition] is [true].
  Future<void> _waitUntilFrame(bool Function() condition, [Completer<void>? completer]) {
    completer ??= Completer<void>();
    if (!condition()) {
      SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
        _waitUntilFrame(condition, completer);
      });
    } else {
      completer.complete();
    }
    return completer.future;
  }

  /// Runs `finder` repeatedly until it finds one or more [Element]s.
  Future<Finder> _waitForElement(Finder finder) async {
    if (frameSync)
      await _waitUntilFrame(() => binding.transientCallbackCount == 0);
    await _waitUntilFrame(() => finder.precache());
    if (frameSync)
      await _waitUntilFrame(() => binding.transientCallbackCount == 0);
    return finder;
  }

  @override
  Future<void> tap(Finder finder, { int? pointer, int buttons = kPrimaryButton, bool warnIfMissed = true }) async {
    await super.tap(await _waitForElement(finder), pointer: pointer, buttons: buttons, warnIfMissed: warnIfMissed);
  }

  Future<void> scrollIntoView(Finder finder, {required double alignment}) async {
    final Finder target = await _waitForElement(finder);
    await Scrollable.ensureVisible(target.evaluate().single, duration: const Duration(milliseconds: 100), alignment: alignment);
  }
}
