// 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/devices.dart';
import '../framework/framework.dart';
import '../framework/task_result.dart';
import '../framework/utils.dart';

const String _kOrgName = 'com.example.activitydestroy';

final RegExp _lifecycleSentinelRegExp = RegExp(r'==== lifecycle\: (.+) ====');

/// Tests the following Android lifecycles: Activity#onStop(), Activity#onResume(), Activity#onPause(),
/// and Activity#onDestroy() from Dart perspective in debug, profile, and release modes.
TaskFunction androidLifecyclesTest({
  Map<String, String>? environment,
}) {
  final Directory tempDir = Directory.systemTemp
      .createTempSync('flutter_devicelab_activity_destroy.');
  return () async {
    try {
      section('Create app');
      await inDirectory(tempDir, () async {
        await flutter(
          'create',
          options: <String>[
            '--platforms',
            'android',
            '--org',
            _kOrgName,
            '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(r'''
 import 'package:flutter/widgets.dart';

class LifecycleObserver extends WidgetsBindingObserver {
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print('==== lifecycle: $state ====');
  }
}

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  WidgetsBinding.instance.addObserver(LifecycleObserver());
  runApp(Container());
}
''', flush: true);

      Future<TaskResult> runTestFor(String mode) async {
        final AndroidDevice device = await devices.workingDevice as AndroidDevice;
        await device.unlock();

        section('Flutter run on device running API level ${device.apiLevel} (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']),
          );
        });

        final StreamController<String> lifecyles = StreamController<String>();
        final StreamIterator<String> lifecycleItr = StreamIterator<String>(lifecyles.stream);

        final StreamSubscription<void> stdout = run.stdout
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String log) {
            final RegExpMatch? match = _lifecycleSentinelRegExp.firstMatch(log);
              print('stdout: $log');
              if (match == null) {
                return;
              }
              final String lifecycle = match[1]!;
              print('stdout: Found app lifecycle: $lifecycle');
              lifecyles.add(lifecycle);
          });

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

        Future<void> expectedLifecycle(String expected) async {
          section('Wait for lifecycle: $expected (mode: $mode)');
          await lifecycleItr.moveNext();
          final String got = lifecycleItr.current;
          if (expected != got) {
            throw TaskResult.failure('expected lifecycles: `$expected`, but got` $got`');
          }
        }

        await expectedLifecycle('AppLifecycleState.resumed');

        section('Toggling app switch (mode: $mode)');
        await device.shellExec('input', <String>['keyevent', 'KEYCODE_APP_SWITCH']);

        await expectedLifecycle('AppLifecycleState.inactive');
        if (device.apiLevel == 28) { // Device lab currently runs 28.
          await expectedLifecycle('AppLifecycleState.paused');
          await expectedLifecycle('AppLifecycleState.detached');
        }

        section('Bring activity to foreground (mode: $mode)');
        await device.shellExec('am', <String>['start', '-n', '$_kOrgName.app/.MainActivity']);

        await expectedLifecycle('AppLifecycleState.resumed');

        section('Launch Settings app (mode: $mode)');
        await device.shellExec('am', <String>['start', '-a', 'android.settings.SETTINGS']);

        await expectedLifecycle('AppLifecycleState.inactive');
        if (device.apiLevel == 28) { // Device lab currently runs 28.
          await expectedLifecycle('AppLifecycleState.paused');
          await expectedLifecycle('AppLifecycleState.detached');
        }

        section('Bring activity to foreground (mode: $mode)');
        await device.shellExec('am', <String>['start', '-n', '$_kOrgName.app/.MainActivity']);

        await expectedLifecycle('AppLifecycleState.resumed');

        run.kill();

        section('Stop subscriptions (mode: $mode)');

        await lifecycleItr.cancel();
        await lifecyles.close();
        await stdout.cancel();
        await stderr.cancel();
        return TaskResult.success(null);
      }

      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);
    } on TaskResult catch (error) {
      return error;
    } finally {
      rmTree(tempDir);
    }
  };
}
