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

import 'package:flutter_gallery/gallery/demos.dart';
import 'package:flutter_gallery/gallery/app.dart' show GalleryApp;

// 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(WidgetsBinding binding) : 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 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 }) async {
    await super.tap(await _waitForElement(finder), pointer: pointer, buttons: buttons);
  }

  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);
  }
}
