// Copyright 2013 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:dir_contents_diff/dir_contents_diff.dart' show dirContentsDiff;
import 'package:engine_repo_tools/engine_repo_tools.dart';
import 'package:path/path.dart';
import 'package:process/process.dart';
import 'package:skia_gold_client/skia_gold_client.dart';

import 'utils/adb_logcat_filtering.dart';
import 'utils/environment.dart';
import 'utils/logs.dart';
import 'utils/options.dart';
import 'utils/process_manager_extension.dart';
import 'utils/screenshot_transformer.dart';

// If you update the arguments, update the documentation in the README.md file.
void main(List<String> args) async {
  // Get some basic environment information to guide the rest of the program.
  final Environment environment = Environment(
    isCi: Platform.environment['LUCI_CONTEXT'] != null,
    showVerbose: Options.showVerbose(args),
    logsDir: Platform.environment['FLUTTER_LOGS_DIR'],
  );

  // Determine if the CWD is within an engine checkout.
  final Engine? localEngineDir = Engine.tryFindWithin();

  // Show usage if requested.
  if (Options.showUsage(args)) {
    stdout.writeln(Options.usage(
      environment: environment,
      localEngineDir: localEngineDir,
    ));
    return;
  }

  // Parse the command line arguments.
  final Options options;
  try {
    options = Options.parse(
      args,
      environment: environment,
      localEngine: localEngineDir,
    );
  } on FormatException catch (error) {
    stderr.writeln(error);
    stderr.writeln(Options.usage(
      environment: environment,
      localEngineDir: localEngineDir,
    ));
    exitCode = 1;
    return;
  }

  // Capture CTRL-C.
  late final StreamSubscription<void> onSigint;

  // Capture requested termination. The goal is to catch timeouts.
  late final StreamSubscription<void> onSigterm;
  void cancelSignalHandlers() {
    onSigint.cancel();
    onSigterm.cancel();
  }
  runZonedGuarded(
    () async {
      onSigint = ProcessSignal.sigint.watch().listen((_) {
        cancelSignalHandlers();
        panic(<String>['Received SIGINT']);
      });
      onSigterm = ProcessSignal.sigterm.watch().listen((_) {
        cancelSignalHandlers();
        panic(<String>['Received SIGTERM']);
      });
      await _run(
        verbose: options.verbose,
        outDir: Directory(options.outDir),
        adb: File(options.adb),
        smokeTestFullPath: options.smokeTest,
        useSkiaGold: options.useSkiaGold,
        enableImpeller: options.enableImpeller,
        impellerBackend: _ImpellerBackend.tryParse(options.impellerBackend),
        logsDir: Directory(options.logsDir),
        contentsGolden: options.outputContentsGolden,
        ndkStack: options.ndkStack,
        forceSurfaceProducerSurfaceTexture: options.forceSurfaceProducerSurfaceTexture,
        prefixLogsPerRun: options.prefixLogsPerRun,
        recordScreen: options.recordScreen,
      );
      onSigint.cancel();
      exit(0);
    },
    (Object error, StackTrace stackTrace) {
      onSigint.cancel();
      if (error is! Panic) {
        stderr.writeln('Unhandled error: $error');
        stderr.writeln(stackTrace);
      }
      exitCode = 1;
    },
  );
}

const int _tcpPort = 3001;

enum _ImpellerBackend {
  vulkan,
  opengles;

  static _ImpellerBackend? tryParse(String? value) {
    for (final _ImpellerBackend backend in _ImpellerBackend.values) {
      if (backend.name == value) {
        return backend;
      }
    }
    return null;
  }
}

Future<void> _run({
  required bool verbose,
  required Directory outDir,
  required File adb,
  required String? smokeTestFullPath,
  required bool useSkiaGold,
  required bool enableImpeller,
  required _ImpellerBackend? impellerBackend,
  required Directory logsDir,
  required String? contentsGolden,
  required String ndkStack,
  required bool forceSurfaceProducerSurfaceTexture,
  required bool prefixLogsPerRun,
  required bool recordScreen,
}) async {
  const ProcessManager pm = LocalProcessManager();
  final String scenarioAppPath = join(outDir.path, 'scenario_app');

  // Due to the CI environment, the logs directory persists between runs and
  // even different builds. Because we're checking the output directory after
  // each run, we need a clean logs directory to avoid false positives.
  //
  // Only after the runner is done, we can move the logs to the final location.
  //
  // See [_copyFiles] below and https://github.com/flutter/flutter/issues/144402.
  final Directory finalLogsDir = logsDir..createSync(recursive: true);
  logsDir = Directory.systemTemp.createTempSync('scenario_app_test_logs.');
  final String logcatPath = join(logsDir.path, 'logcat.txt');

  final String screenshotPath = logsDir.path;
  final String apkOutPath = join(scenarioAppPath, 'app', 'outputs', 'apk');
  final File testApk = File(join(apkOutPath, 'androidTest', 'debug', 'app-debug-androidTest.apk'));
  final File appApk = File(join(apkOutPath, 'debug', 'app-debug.apk'));
  log('writing logs and screenshots to ${logsDir.path}');

  if (!testApk.existsSync()) {
    panic(<String>[
      'test apk does not exist: ${testApk.path}',
      'make sure to build the selected engine variant'
    ]);
  }

  if (!appApk.existsSync()) {
    panic(<String>[
      'app apk does not exist: ${appApk.path}',
      'make sure to build the selected engine variant'
    ]);
  }

  // Start a TCP socket in the host, and forward it to the device that runs the tests.
  // This allows the test process to start a connection with the host, and write the bytes
  // for the screenshots.
  // On LUCI, the host uploads the screenshots to Skia Gold.
  SkiaGoldClient? skiaGoldClient;
  late final ServerSocket server;
  final List<Future<void>> pendingComparisons = <Future<void>>[];
  final List<Socket> pendingConnections = <Socket>[];
  int comparisonsFailed = 0;
  await step('Starting server...', () async {
    server = await ServerSocket.bind(InternetAddress.anyIPv4, _tcpPort);
    if (verbose) {
      stdout.writeln('listening on host ${server.address.address}:${server.port}');
    }
    server.listen((Socket client) {
      if (verbose) {
        stdout.writeln('client connected ${client.remoteAddress.address}:${client.remotePort}');
      }
      pendingConnections.add(client);
      client.transform(const ScreenshotBlobTransformer()).listen((Screenshot screenshot) async {
        final String fileName = screenshot.filename;
        final String filePath = join(screenshotPath, fileName);
        {
          const String remotePath = '/data/local/tmp/flutter_screenshot.png';
          ProcessResult result = await pm.run(<String>['adb', 'shell', 'screencap', '-p', remotePath]);
          if (result.exitCode != 0) {
            panic(<String>['Failed to capture screenshot']);
          }
          result = await pm.run(
            <String>['adb', 'pull', remotePath, filePath],
          );
          if (result.exitCode != 0) {
            panic(<String>['Failed to pull screenshot']);
          }
          result = await pm.run(<String>['adb', 'shell', 'rm', remotePath]);
          if (result.exitCode != 0) {
            stderr.writeln('Warning: failed to delete old screenshot on device.');
          }
        }
        // Write a single byte into the socket as a signal to ScreenshotUtil.java
        // that the screenshot was taken.
        client.write(0x8);

        assert(skiaGoldClient != null, 'expected Skia Gold client');
        final File goldenFile = File(filePath);
        if (verbose) {
          log('wrote ${goldenFile.absolute.path}');
        }
        if (SkiaGoldClient.isAvailable()) {
          final Future<void> comparison = skiaGoldClient!
              .addImg(
                fileName,
                goldenFile,
                screenshotSize: screenshot.pixelCount,
                // Each color channel can be off by 2.
                pixelColorDelta: 8,
              )
              .then((_) => logImportant('skia gold comparison succeeded: $fileName'))
              .catchError((Object error) {
            logWarning('skia gold comparison failed: $error');
            comparisonsFailed++;
          });
          pendingComparisons.add(comparison);
        }
      }, onDone: () {
        pendingConnections.remove(client);
      });
    });
  });

  late Process logcatProcess;
  late Future<int> logcatProcessExitCode;
  _ImpellerBackend? actualImpellerBackend;
  Process? screenRecordProcess;

  final IOSink logcat = File(logcatPath).openWrite();
  try {
    await step('Creating screenshot directory `$screenshotPath`...', () async {
      Directory(screenshotPath).createSync(recursive: true);
    });

    await step('Starting logcat...', () async {
      final int exitCode = await pm.runAndForward(<String>[adb.path, 'logcat', '-c']);
      if (exitCode != 0) {
        panic(<String>['could not clear logs']);
      }

      logcatProcess = await pm.start(<String>[adb.path, 'logcat', '-T', '1']);
      final (Future<int> logcatExitCode, Stream<String> logcatOutput) = getProcessStreams(logcatProcess);

      logcatProcessExitCode = logcatExitCode;
      String? filterProcessId;

      logcatOutput.listen((String line) {
        // Always write to the full log.
        logcat.writeln(line);
        if (enableImpeller && actualImpellerBackend == null && line.contains('Using the Impeller rendering backend')) {
          if (line.contains('OpenGLES')) {
            actualImpellerBackend = _ImpellerBackend.opengles;
          } else if (line.contains('Vulkan')) {
            actualImpellerBackend = _ImpellerBackend.vulkan;
          } else {
            panic(<String>[
              'Impeller was enabled, but $line did not contain "OpenGLES" or "Vulkan".',
            ]);
          }
        }

        // Conditionally parse and write to stderr.
        final AdbLogLine? adbLogLine = AdbLogLine.tryParse(line);
        if (verbose || adbLogLine == null) {
          log(line);
          return;
        }

        // If we haven't already found a process ID, try to find one.
        // The process ID will help us filter out logs from other processes.
        filterProcessId ??= adbLogLine.tryParseProcess();

        // If this is a "verbose" log, possibly skip it.
        final bool isVerbose = adbLogLine.isVerbose(filterProcessId: filterProcessId);
        if (isVerbose || filterProcessId == null) {
          // We've requested verbose output, so print everything.
          if (verbose) {
            adbLogLine.printFormatted();
          }
          return;
        }

        // It's a non-verbose log, so print it.
        adbLogLine.printFormatted();
      }, onError: (Object? err) {
        if (verbose) {
          logWarning('logcat stream error: $err');
        }
      });
    });

    await step('Configuring emulator...', () async {
      final int exitCode = await pm.runAndForward(<String>[
        adb.path,
        'shell',
        'settings',
        'put',
        'secure',
        'immersive_mode_confirmations',
        'confirmed',
      ]);
      if (exitCode != 0) {
        panic(<String>['could not configure emulator']);
      }
    });

    await step('Get API level of connected device...', () async {
      final ProcessResult apiLevelProcessResult = await pm.run(<String>[adb.path, 'shell', 'getprop', 'ro.build.version.sdk']);
      if (apiLevelProcessResult.exitCode != 0) {
        panic(<String>['could not get API level of the connected device']);
      }
      final String connectedDeviceAPILevel = (apiLevelProcessResult.stdout as String).trim();
      final Map<String, String> dimensions = <String, String>{
        'AndroidAPILevel': connectedDeviceAPILevel,
        'GraphicsBackend': enableImpeller ? 'impeller-${impellerBackend!.name}' : 'skia',
        'ForceSurfaceProducerSurfaceTexture': '$forceSurfaceProducerSurfaceTexture'
      };
      log('using dimensions: ${json.encode(dimensions)}');
      skiaGoldClient = SkiaGoldClient(
        outDir,
        dimensions: dimensions,
      );
    });

    await step('Skia Gold auth...', () async {
      if (SkiaGoldClient.isAvailable()) {
        await skiaGoldClient!.auth();
        log('skia gold client is available');
      } else {
        if (useSkiaGold) {
          panic(<String>['skia gold client is unavailable']);
        } else {
          log('skia gold client is unavaialble');
        }
      }
    });

    await step('Reverse port...', () async {
      final int exitCode = await pm.runAndForward(<String>[adb.path, 'reverse', 'tcp:3000', 'tcp:$_tcpPort']);
      if (exitCode != 0) {
        panic(<String>['could not forward port']);
      }
    });

    await step('Installing app APK...', () async {
      final int exitCode = await pm.runAndForward(<String>[adb.path, 'install', appApk.path]);
      if (exitCode != 0) {
        panic(<String>['could not install app apk']);
      }
    });

    await step('Installing test APK...', () async {
      final int exitCode = await pm.runAndForward(<String>[adb.path, 'install', testApk.path]);
      if (exitCode != 0) {
        panic(<String>['could not install test apk']);
      }
    });

    if (recordScreen) {
      await step('Recording screen...', () async {
        // Create a /tmp directory on the device to store the screen recording.
        final int exitCode = await pm.runAndForward(<String>[
          adb.path,
          'shell',
          'mkdir',
          '-p',
          join(_emulatorStoragePath, 'tmp'),
        ]);
        if (exitCode != 0) {
          panic(<String>['could not create /tmp directory on device']);
        }
        final String screenRecordingPath = join(
          _emulatorStoragePath,
          'tmp',
          'screen.mp4',
        );
        screenRecordProcess = await pm.start(<String>[
          adb.path,
          'shell',
          'screenrecord',
          '--time-limit=0',
          '--bugreport',
          screenRecordingPath,
        ]);
        log('writing screen recording to $screenRecordingPath');
      });
    }

    await step('Running instrumented tests...', () async {
      final (int exitCode, StringBuffer out) = await pm.runAndCapture(<String>[
        adb.path,
        'shell',
        'am',
        'instrument',
        '-w',
        '--no-window-animation',
        if (smokeTestFullPath != null)
          '-e class $smokeTestFullPath',
        if (enableImpeller)
          '-e enable-impeller true',
        if (impellerBackend != null)
          '-e impeller-backend ${impellerBackend.name}',
        if (forceSurfaceProducerSurfaceTexture)
          '-e force-surface-producer-surface-texture true',
        'dev.flutter.scenarios.test/dev.flutter.TestRunner',
      ]);
      if (exitCode != 0) {
        panic(<String>['instrumented tests failed to run']);
      }
      // Unfortunately adb shell am instrument does not return a non-zero exit
      // code when tests fail, but it does seem to print "FAILURES!!!" to
      // stdout, so we can use that as a signal that something went wrong.
      if (out.toString().contains('FAILURES!!!')) {
        stdout.write(out);
        panic(<String>['1 or more tests failed']);
      } else if (comparisonsFailed > 0) {
        panic(<String>['$comparisonsFailed Skia Gold comparisons failed']);
      }
    });


    if (enableImpeller) {
      await step('Validating Impeller...', () async {
        final _ImpellerBackend expectedImpellerBackend = impellerBackend ?? _ImpellerBackend.vulkan;
        if (actualImpellerBackend != expectedImpellerBackend) {
          panic(<String>[
            '--enable-impeller was specified and expected to find "${expectedImpellerBackend.name}", which did not match "${actualImpellerBackend?.name ?? '<impeller disabled>'}".',
          ]);
        }
      });
    }

    await step('Wait for pending Skia gold comparisons...', () async {
      await Future.wait(pendingComparisons);
    });

    final bool allTestsRun = smokeTestFullPath == null;
    final bool checkGoldens = contentsGolden != null;
    if (allTestsRun && checkGoldens) {
      // Check the output here.
      await step('Check output files...', () async {
        // TODO(matanlurey): Resolve this in a better way. On CI this file always exists.
        File(join(screenshotPath, 'noop.txt')).writeAsStringSync('');
        // TODO(gaaclarke): We should move this into dir_contents_diff.
        final String diffScreenhotPath = absolute(screenshotPath);
        _withTemporaryCwd(absolute(dirname(contentsGolden)), () {
          final int exitCode = dirContentsDiff(basename(contentsGolden), diffScreenhotPath);
          if (exitCode != 0) {
            panic(<String>['Output contents incorrect.']);
          }
        });
      });
    }
  } finally {
    // The finally clause is entered if:
    // - The tests have completed successfully.
    // - Any step has failed.
    //
    // Do *NOT* throw exceptions or errors in this block, as these are cleanup
    // steps and the program is about to exit. Instead, just log the error and
    // continue with the cleanup.

    await server.close();
    for (final Socket client in pendingConnections.toList()) {
      client.close();
    }

    await step('Killing test app and test runner...', () async {
      final int exitCode = await pm.runAndForward(<String>[adb.path, 'shell', 'am', 'force-stop', 'dev.flutter.scenarios']);
      if (exitCode != 0) {
        logError('could not kill test app');
      }
    });

    if (screenRecordProcess != null) {
      await step('Killing screen recording process...', () async {
        // Kill the screen recording process.
        screenRecordProcess!.kill(ProcessSignal.sigkill);
        await screenRecordProcess!.exitCode;

        // Pull the screen recording from the device.
        final String screenRecordingPath = join(
          _emulatorStoragePath,
          'tmp',
          'screen.mp4',
        );
        final String screenRecordingLocalPath = join(
          logsDir.path,
          'screen.mp4',
        );
        final int exitCode = await pm.runAndForward(<String>[
          adb.path,
          'pull',
          screenRecordingPath,
          screenRecordingLocalPath,
        ]);
        if (exitCode != 0) {
          logError('could not pull screen recording from device');
        }

        log('wrote screen recording to $screenRecordingLocalPath');

        // Remove the screen recording from the device.
        final int removeExitCode = await pm.runAndForward(<String>[
          adb.path,
          'shell',
          'rm',
          screenRecordingPath,
        ]);
        if (removeExitCode != 0) {
          logError('could not remove screen recording from device');
        }
      });
    }

    await step('Killing logcat process...', () async {
      final bool delivered = logcatProcess.kill(ProcessSignal.sigkill);
      assert(delivered);
      await logcatProcessExitCode;
    });

    await step('Flush logcat...', () async {
      await logcat.flush();
      await logcat.close();
      log('wrote logcat to $logcatPath');

      // Copy the logs to the final location.
      // Optionally prefix the logs with a run number and backend name.
      // See https://github.com/flutter/flutter/issues/144402.
      final StringBuffer prefix = StringBuffer();
      if (prefixLogsPerRun) {
        final int rerunNumber = _getAndIncrementRerunNumber(finalLogsDir.path);
        prefix.write('run_$rerunNumber.');
        if (enableImpeller) {
          prefix.write('impeller');
        } else {
          prefix.write('skia');
        }
        if (enableImpeller) {
          prefix.write('_${impellerBackend!.name}');
        }
        if (forceSurfaceProducerSurfaceTexture) {
          prefix.write('_force-st');
        }
        prefix.write('.');
      }
      _copyFiles(
        source: logsDir,
        destination: finalLogsDir,
        prefix: prefix.toString(),
      );
    });

    await step('Symbolize stack traces', () async {
      final ProcessResult result = await pm.run(
        <String>[
          ndkStack,
          '-sym',
          outDir.path,
          '-dump',
          logcatPath,
        ],
      );
      if (result.exitCode != 0) {
        panic(<String>['Failed to symbolize stack traces']);
      }
    });

    await step('Remove reverse port...', () async {
      final int exitCode = await pm.runAndForward(<String>[
        adb.path,
        'reverse',
        '--remove',
        'tcp:3000',
      ]);
      if (exitCode != 0) {
        logError('could not unforward port');
      }
    });

    await step('Uninstalling app APK...', () async {
      final int exitCode = await pm.runAndForward(<String>[
        adb.path,
        'uninstall',
        'dev.flutter.scenarios',
      ]);
      if (exitCode != 0) {
        logError('could not uninstall app apk');
      }
    });

    await step('Uninstalling test APK...', () async {
      final int exitCode = await pm.runAndForward(<String>[
        adb.path,
        'uninstall',
        'dev.flutter.scenarios.test',
      ]);
      if (exitCode != 0) {
        logError('could not uninstall app apk');
      }
    });
  }
}

const String _emulatorStoragePath = '/storage/emulated/0/Download';

void _withTemporaryCwd(String path, void Function() callback) {
  final String originalCwd = Directory.current.path;
  Directory.current = Directory(path).path;

  try {
    callback();
  } finally {
    Directory.current = originalCwd;
  }
}

/// Reads the file named `reruns.txt` in the logs directory and returns the number of reruns.
///
/// If the file does not exist, it is created with the number 1 and that number is returned.
int _getAndIncrementRerunNumber(String logsDir) {
  final File rerunFile = File(join(logsDir, 'reruns.txt'));
  if (!rerunFile.existsSync()) {
    rerunFile.writeAsStringSync('1');
    return 1;
  }
  final int rerunNumber = int.parse(rerunFile.readAsStringSync()) + 1;
  rerunFile.writeAsStringSync(rerunNumber.toString());
  return rerunNumber;
}

/// Copies the contents of [source] to [destination], optionally adding a [prefix] to the destination path.
///
/// This function is used to copy the screenshots from the device to the logs directory.
void _copyFiles({
  required Directory source,
  required Directory destination,
  String prefix = '',
}) {
  for (final FileSystemEntity entity in source.listSync()) {
    if (entity is File) {
      entity.copySync(join(destination.path, prefix + basename(entity.path)));
    }
  }
}
