// 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 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as path;

import '../framework/framework.dart';
import '../framework/task_result.dart';
import '../framework/utils.dart';

const List<String> kSentinelStr = <String>[
  '==== sentinel #1 ====',
  '==== sentinel #2 ====',
  '==== sentinel #3 ====',
];

/// Tests that Choreographer#doFrame finishes during application startup.
/// This test fails if the application hangs during this period.
/// https://ui.perfetto.dev/#!/?s=da6628c3a92456ae8fa3f345d0186e781da77e90fc8a64d073e9fee11d1e65
/// Regression test for https://github.com/flutter/flutter/issues/98973
TaskFunction androidChoreographerDoFrameTest({
  Map<String, String>? environment,
}) {
  final Directory tempDir = Directory.systemTemp
      .createTempSync('flutter_devicelab_android_surface_recreation.');
  return () async {
    try {
      section('Create app');
      await inDirectory(tempDir, () async {
        await flutter(
          'create',
          options: <String>[
            '--platforms',
            'android',
            'app',
          ],
          environment: environment,
        );
      });

      final File mainDart = File(path.join(
        tempDir.absolute.path,
        'app',
        'lib',
        'main.dart',
      ));
      if (!mainDart.existsSync()) {
        return TaskResult.failure('${mainDart.path} does not exist');
      }

      section('Patch lib/main.dart');
      await mainDart.writeAsString('''
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  print('${kSentinelStr[0]}');
  await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);

  print('${kSentinelStr[1]}');
  // If the Android UI thread is blocked, then this Future won't resolve.
  await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);

  print('${kSentinelStr[2]}');
  runApp(
    Container(
      decoration: BoxDecoration(
        color: const Color(0xff7c94b6),
      ),
    ),
  );
}
''', flush: true);

      Future<TaskResult> runTestFor(String mode) async {
        int nextCompleterIdx = 0;
        final Map<String, Completer<void>> sentinelCompleters = <String, Completer<void>>{};
        for (final String sentinel in kSentinelStr) {
          sentinelCompleters[sentinel] = Completer<void>();
        }

        section('Flutter run (mode: $mode)');
        late Process run;
        await inDirectory(path.join(tempDir.path, 'app'), () async {
          run = await startProcess(
            path.join(flutterDirectory.path, 'bin', 'flutter'),
            flutterCommandArgs('run', <String>['--$mode', '--verbose']),
          );
        });

        int currSentinelIdx = 0;
        final StreamSubscription<void> stdout = run.stdout
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String line) {
            if (currSentinelIdx < sentinelCompleters.keys.length &&
                line.contains(sentinelCompleters.keys.elementAt(currSentinelIdx))) {
              sentinelCompleters.values.elementAt(currSentinelIdx).complete();
              currSentinelIdx++;
              print('stdout(MATCHED): $line');
            } else {
              print('stdout: $line');
            }
          });

        final StreamSubscription<void> stderr = run.stderr
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String line) {
            print('stderr: $line');
          });

        final Completer<void> exitCompleter = Completer<void>();

        unawaited(run.exitCode.then((int exitCode) {
          exitCompleter.complete();
        }));

        section('Wait for sentinels (mode: $mode)');
        for (final Completer<void> completer in sentinelCompleters.values) {
          if (nextCompleterIdx == 0) {
            // Don't time out because we don't know how long it would take to get the first log.
            await Future.any<dynamic>(
              <Future<dynamic>>[
                completer.future,
                exitCompleter.future,
              ],
            );
          } else {
            try {
              // Time out since this should not take 1s after the first log was received.
              await Future.any<dynamic>(
                <Future<dynamic>>[
                  completer.future.timeout(const Duration(seconds: 1)),
                  exitCompleter.future,
                ],
              );
            } on TimeoutException {
              break;
            }
          }
          if (exitCompleter.isCompleted) {
            // The process exited.
            break;
          }
          nextCompleterIdx++;
        }

        section('Quit app (mode: $mode)');
        run.stdin.write('q');
        await exitCompleter.future;

        section('Stop listening to stdout and stderr (mode: $mode)');
        await stdout.cancel();
        await stderr.cancel();
        run.kill();

        if (nextCompleterIdx == sentinelCompleters.values.length) {
          return TaskResult.success(null);
        }
        final String nextSentinel = sentinelCompleters.keys.elementAt(nextCompleterIdx);
        return TaskResult.failure('Expected sentinel `$nextSentinel` in mode $mode');
      }

      final TaskResult debugResult = await runTestFor('debug');
      if (debugResult.failed) {
        return debugResult;
      }

      final TaskResult profileResult = await runTestFor('profile');
      if (profileResult.failed) {
        return profileResult;
      }

      final TaskResult releaseResult = await runTestFor('release');
       if (releaseResult.failed) {
        return releaseResult;
      }

      return TaskResult.success(null);
    } finally {
      rmTree(tempDir);
    }
  };
}
