// 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 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:pool/pool.dart';
import 'package:vm_service/vm_service.dart' as vm_service;

import 'base/context.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/platform.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'compile.dart';
import 'convert.dart';
import 'dart/package_map.dart';
import 'devfs.dart';
import 'device.dart';
import 'features.dart';
import 'globals.dart' as globals;
import 'project.dart';
import 'reporting/reporting.dart';
import 'resident_runner.dart';
import 'vmservice.dart';

ProjectFileInvalidator get projectFileInvalidator => context.get<ProjectFileInvalidator>() ?? ProjectFileInvalidator(
  fileSystem: globals.fs,
  platform: globals.platform,
  logger: globals.logger,
);

HotRunnerConfig? get hotRunnerConfig => context.get<HotRunnerConfig>();

class HotRunnerConfig {
  /// Should the hot runner assume that the minimal Dart dependencies do not change?
  bool stableDartDependencies = false;

  /// Whether the hot runner should scan for modified files asynchronously.
  bool asyncScanning = false;

  /// A hook for implementations to perform any necessary initialization prior
  /// to a hot restart. Should return true if the hot restart should continue.
  Future<bool?> setupHotRestart() async {
    return true;
  }

  /// A hook for implementations to perform any necessary initialization prior
  /// to a hot reload. Should return true if the hot restart should continue.
  Future<bool?> setupHotReload() async {
    return true;
  }

  /// A hook for implementations to perform any necessary cleanup after the
  /// devfs sync is complete. At this point the flutter_tools no longer needs to
  /// access the source files and assets.
  void updateDevFSComplete() {}

  /// A hook for implementations to perform any necessary operations right
  /// before the runner is about to be shut down.
  Future<void> runPreShutdownOperations() async {
    return;
  }
}

const bool kHotReloadDefault = true;

class DeviceReloadReport {
  DeviceReloadReport(this.device, this.reports);

  FlutterDevice? device;
  List<vm_service.ReloadReport> reports; // List has one report per Flutter view.
}

class HotRunner extends ResidentRunner {
  HotRunner(
    super.devices, {
    required super.target,
    required super.debuggingOptions,
    this.benchmarkMode = false,
    this.applicationBinary,
    this.hostIsIde = false,
    super.projectRootPath,
    super.dillOutputPath,
    super.stayResident,
    bool super.ipv6 = false,
    super.machine,
    this.multidexEnabled = false,
    super.devtoolsHandler,
    StopwatchFactory stopwatchFactory = const StopwatchFactory(),
    ReloadSourcesHelper reloadSourcesHelper = _defaultReloadSourcesHelper,
    ReassembleHelper reassembleHelper = _defaultReassembleHelper,
  }) : _stopwatchFactory = stopwatchFactory,
       _reloadSourcesHelper = reloadSourcesHelper,
       _reassembleHelper = reassembleHelper,
       super(
          hotMode: true,
        );

  final StopwatchFactory _stopwatchFactory;
  final ReloadSourcesHelper _reloadSourcesHelper;
  final ReassembleHelper _reassembleHelper;

  final bool benchmarkMode;
  final File? applicationBinary;
  final bool hostIsIde;
  final bool multidexEnabled;

  /// When performing a hot restart, the tool needs to upload a new main.dart.dill to
  /// each attached device's devfs. Replacing the existing file is not safe and does
  /// not work at all on the windows embedder, because the old dill file will still be
  /// memory-mapped by the embedder. To work around this issue, the tool will alternate
  /// names for the uploaded dill, sometimes inserting `.swap`. Since the active dill will
  /// never be replaced, there is no risk of writing the file while the embedder is attempting
  /// to read from it. This also avoids filling up the devfs, if a incrementing counter was
  /// used instead.
  ///
  /// This is only used for hot restart, incremental dills uploaded as part of the hot
  /// reload process do not have this issue.
  bool _swap = false;

  /// Whether the resident runner has correctly attached to the running application.
  bool _didAttach = false;

  final Map<String, List<int>> benchmarkData = <String, List<int>>{};

  DateTime? firstBuildTime;

  String? _targetPlatform;
  String? _sdkName;
  bool? _emulator;

  Future<void> _calculateTargetPlatform() async {
    if (_targetPlatform != null) {
      return;
    }

    if (flutterDevices.length == 1) {
      final Device device = flutterDevices.first.device!;
      _targetPlatform = getNameForTargetPlatform(await device.targetPlatform);
      _sdkName = await device.sdkNameAndVersion;
      _emulator = await device.isLocalEmulator;
    } else if (flutterDevices.length > 1) {
      _targetPlatform = 'multiple';
      _sdkName = 'multiple';
      _emulator = false;
    } else {
      _targetPlatform = 'unknown';
      _sdkName = 'unknown';
      _emulator = false;
    }
  }

  void _addBenchmarkData(String name, int value) {
    benchmarkData[name] ??= <int>[];
    benchmarkData[name]!.add(value);
  }

  Future<void> _reloadSourcesService(
    String isolateId, {
    bool force = false,
    bool pause = false,
  }) async {
    final OperationResult result = await restart(pause: pause);
    if (!result.isOk) {
      throw vm_service.RPCError(
        'Unable to reload sources',
        RPCErrorCodes.kInternalError,
        '',
      );
    }
  }

  Future<void> _restartService({ bool pause = false }) async {
    final OperationResult result =
      await restart(fullRestart: true, pause: pause);
    if (!result.isOk) {
      throw vm_service.RPCError(
        'Unable to restart',
        RPCErrorCodes.kInternalError,
        '',
      );
    }
  }

  Future<String> _compileExpressionService(
    String isolateId,
    String expression,
    List<String> definitions,
    List<String> typeDefinitions,
    String libraryUri,
    String? klass,
    bool isStatic,
  ) async {
    for (final FlutterDevice? device in flutterDevices) {
      if (device!.generator != null) {
        final CompilerOutput? compilerOutput =
            await device.generator!.compileExpression(expression, definitions,
                typeDefinitions, libraryUri, klass, isStatic);
        if (compilerOutput != null && compilerOutput.expressionData != null) {
          return base64.encode(compilerOutput.expressionData!);
        }
      }
    }
    throw Exception('Failed to compile $expression');
  }

  // Returns the exit code of the flutter tool process, like [run].
  @override
  Future<int> attach({
    Completer<DebugConnectionInfo>? connectionInfoCompleter,
    Completer<void>? appStartedCompleter,
    bool allowExistingDdsInstance = false,
    bool enableDevTools = false,
    bool needsFullRestart = true,
  }) async {
    _didAttach = true;
    try {
      await connectToServiceProtocol(
        reloadSources: _reloadSourcesService,
        restart: _restartService,
        compileExpression: _compileExpressionService,
        getSkSLMethod: writeSkSL,
        allowExistingDdsInstance: allowExistingDdsInstance,
      );
    // Catches all exceptions, non-Exception objects are rethrown.
    } catch (error) { // ignore: avoid_catches_without_on_clauses
      if (error is! Exception && error is! String) {
        rethrow;
      }
      globals.printError('Error connecting to the service protocol: $error');
      return 2;
    }

    if (enableDevTools) {
      // The method below is guaranteed never to return a failing future.
      unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
        devToolsServerAddress: debuggingOptions.devToolsServerAddress,
        flutterDevices: flutterDevices,
      ));
    }

    for (final FlutterDevice? device in flutterDevices) {
      await device!.initLogReader();
      device
        .developmentShaderCompiler
        .configureCompiler(device.targetPlatform, enableImpeller: debuggingOptions.enableImpeller);
    }
    try {
      final List<Uri?> baseUris = await _initDevFS();
      if (connectionInfoCompleter != null) {
        // Only handle one debugger connection.
        connectionInfoCompleter.complete(
          DebugConnectionInfo(
            httpUri: flutterDevices.first.vmService!.httpAddress,
            wsUri: flutterDevices.first.vmService!.wsAddress,
            baseUri: baseUris.first.toString(),
          ),
        );
      }
    } on DevFSException catch (error) {
      globals.printError('Error initializing DevFS: $error');
      return 3;
    }

    final Stopwatch initialUpdateDevFSsTimer = Stopwatch()..start();
    final UpdateFSReport devfsResult = await _updateDevFS(fullRestart: needsFullRestart);
    _addBenchmarkData(
      'hotReloadInitialDevFSSyncMilliseconds',
      initialUpdateDevFSsTimer.elapsed.inMilliseconds,
    );
    if (!devfsResult.success) {
      return 3;
    }

    for (final FlutterDevice? device in flutterDevices) {
      // VM must have accepted the kernel binary, there will be no reload
      // report, so we let incremental compiler know that source code was accepted.
      if (device!.generator != null) {
        device.generator!.accept();
      }
      final List<FlutterView> views = await device.vmService!.getFlutterViews();
      for (final FlutterView view in views) {
        globals.printTrace('Connected to $view.');
      }
    }

    // In fast-start mode, apps are initialized from a placeholder splashscreen
    // app. We must do a restart here to load the program and assets for the
    // real app.
    if (debuggingOptions.fastStart) {
      await restart(
        fullRestart: true,
        reason: 'restart',
        silent: true,
      );
    }

    appStartedCompleter?.complete();

    if (benchmarkMode) {
      // Wait multiple seconds for the isolate to have fully started.
      await Future<void>.delayed(const Duration(seconds: 10));
      // We are running in benchmark mode.
      globals.printStatus('Running in benchmark mode.');
      // Measure time to perform a hot restart.
      globals.printStatus('Benchmarking hot restart');
      await restart(fullRestart: true);
      // Wait multiple seconds to stabilize benchmark on slower device lab hardware.
      // Hot restart finishes when the new isolate is started, not when the new isolate
      // is ready. This process can actually take multiple seconds.
      await Future<void>.delayed(const Duration(seconds: 10));

      globals.printStatus('Benchmarking hot reload');
      // Measure time to perform a hot reload.
      await restart();
      if (stayResident) {
        await waitForAppToFinish();
      } else {
        globals.printStatus('Benchmark completed. Exiting application.');
        await _cleanupDevFS();
        await stopEchoingDeviceLog();
        await exitApp();
      }
      final File benchmarkOutput = globals.fs.file('hot_benchmark.json');
      benchmarkOutput.writeAsStringSync(toPrettyJson(benchmarkData));
      return 0;
    }
    writeVmServiceFile();

    int result = 0;
    if (stayResident) {
      result = await waitForAppToFinish();
    }
    await cleanupAtFinish();
    return result;
  }

  @override
  Future<int> run({
    Completer<DebugConnectionInfo>? connectionInfoCompleter,
    Completer<void>? appStartedCompleter,
    bool enableDevTools = false,
    String? route,
  }) async {
    await _calculateTargetPlatform();

    final Stopwatch appStartedTimer = Stopwatch()..start();
    final File mainFile = globals.fs.file(mainPath);
    firstBuildTime = DateTime.now();

    Duration totalCompileTime = Duration.zero;
    Duration totalLaunchAppTime = Duration.zero;

    final List<Future<bool>> startupTasks = <Future<bool>>[];
    for (final FlutterDevice? device in flutterDevices) {
      // Here we initialize the frontend_server concurrently with the platform
      // build, reducing overall initialization time. This is safe because the first
      // invocation of the frontend server produces a full dill file that the
      // subsequent invocation in devfs will not overwrite.
      await runSourceGenerators();
      if (device!.generator != null) {
        final Stopwatch compileTimer = Stopwatch()..start();
        startupTasks.add(
          device.generator!.recompile(
            mainFile.uri,
            <Uri>[],
            // When running without a provided applicationBinary, the tool will
            // simultaneously run the initial frontend_server compilation and
            // the native build step. If there is a Dart compilation error, it
            // should only be displayed once.
            suppressErrors: applicationBinary == null,
            checkDartPluginRegistry: true,
            dartPluginRegistrant: FlutterProject.current().dartPluginRegistrant,
            outputPath: dillOutputPath,
            packageConfig: debuggingOptions.buildInfo.packageConfig,
            projectRootPath: FlutterProject.current().directory.absolute.path,
            fs: globals.fs,
          ).then((CompilerOutput? output) {
            compileTimer.stop();
            totalCompileTime += compileTimer.elapsed;
            return output?.errorCount == 0;
          })
        );
      }

      final Stopwatch launchAppTimer = Stopwatch()..start();
      startupTasks.add(device.runHot(
        hotRunner: this,
        route: route,
      ).then((int result) {
        totalLaunchAppTime += launchAppTimer.elapsed;
        return result == 0;
      }));
    }

    unawaited(appStartedCompleter?.future.then((_) => HotEvent('reload-ready',
      targetPlatform: _targetPlatform!,
      sdkName: _sdkName!,
      emulator: _emulator!,
      fullRestart: false,
      fastReassemble: false,
      overallTimeInMs: appStartedTimer.elapsed.inMilliseconds,
      compileTimeInMs: totalCompileTime.inMilliseconds,
      transferTimeInMs: totalLaunchAppTime.inMilliseconds,
    ).send()));

    try {
      final List<bool> results = await Future.wait(startupTasks);
      if (!results.every((bool passed) => passed)) {
        appFailedToStart();
        return 1;
      }
      cacheInitialDillCompilation();
    } on Exception catch (err) {
      globals.printError(err.toString());
      appFailedToStart();
      return 1;
    }

    return attach(
      connectionInfoCompleter: connectionInfoCompleter,
      appStartedCompleter: appStartedCompleter,
      enableDevTools: enableDevTools,
      needsFullRestart: false,
    );
  }

  Future<List<Uri?>> _initDevFS() async {
    final String fsName = globals.fs.path.basename(projectRootPath);
    return <Uri?>[
      for (final FlutterDevice? device in flutterDevices)
        await device!.setupDevFS(
          fsName,
          globals.fs.directory(projectRootPath),
        ),
    ];
  }

  Future<UpdateFSReport> _updateDevFS({ bool fullRestart = false }) async {
    final bool isFirstUpload = !assetBundle.wasBuiltOnce();
    final bool rebuildBundle = assetBundle.needsBuild();
    if (rebuildBundle) {
      globals.printTrace('Updating assets');
      final int result = await assetBundle.build(packagesPath: '.packages');
      if (result != 0) {
        return UpdateFSReport();
      }
    }

    final Stopwatch findInvalidationTimer = _stopwatchFactory.createStopwatch('updateDevFS')..start();
    final DevFS devFS = flutterDevices[0].devFS!;
    final InvalidationResult invalidationResult = await projectFileInvalidator.findInvalidated(
      lastCompiled: devFS.lastCompiled,
      urisToMonitor: devFS.sources,
      packagesPath: packagesFilePath,
      asyncScanning: hotRunnerConfig!.asyncScanning,
      packageConfig: devFS.lastPackageConfig
          ?? debuggingOptions.buildInfo.packageConfig,
    );
    findInvalidationTimer.stop();
    final File entrypointFile = globals.fs.file(mainPath);
    if (!entrypointFile.existsSync()) {
      globals.printError(
        'The entrypoint file (i.e. the file with main()) ${entrypointFile.path} '
        'cannot be found. Moving or renaming this file will prevent changes to '
        'its contents from being discovered during hot reload/restart until '
        'flutter is restarted or the file is restored.'
      );
    }
    final UpdateFSReport results = UpdateFSReport(
      success: true,
      scannedSourcesCount: devFS.sources.length,
      findInvalidatedDuration: findInvalidationTimer.elapsed,
    );
    for (final FlutterDevice? device in flutterDevices) {
      results.incorporateResults(await device!.updateDevFS(
        mainUri: entrypointFile.absolute.uri,
        target: target,
        bundle: assetBundle,
        firstBuildTime: firstBuildTime,
        bundleFirstUpload: isFirstUpload,
        bundleDirty: !isFirstUpload && rebuildBundle,
        fullRestart: fullRestart,
        projectRootPath: projectRootPath,
        pathToReload: getReloadPath(fullRestart: fullRestart, swap: _swap),
        invalidatedFiles: invalidationResult.uris!,
        packageConfig: invalidationResult.packageConfig!,
        dillOutputPath: dillOutputPath,
      ));
    }
    return results;
  }

  void _resetDirtyAssets() {
    for (final FlutterDevice device in flutterDevices) {
      final DevFS? devFS = device.devFS;
      if (devFS == null) {
        // This is sometimes null, however we don't know why and have not been
        // able to reproduce, https://github.com/flutter/flutter/issues/108653
        continue;
      }
      devFS.assetPathsToEvict.clear();
      devFS.shaderPathsToEvict.clear();
      devFS.scenePathsToEvict.clear();
    }
  }

  Future<void> _cleanupDevFS() async {
    final List<Future<void>> futures = <Future<void>>[];
    for (final FlutterDevice device in flutterDevices) {
      if (device.devFS != null) {
        // Cleanup the devFS, but don't wait indefinitely.
        // We ignore any errors, because it's not clear what we would do anyway.
        futures.add(device.devFS!.destroy()
          .timeout(const Duration(milliseconds: 250))
          .catchError((Object? error) {
            globals.printTrace('Ignored error while cleaning up DevFS: $error');
          }));
      }
      device.devFS = null;
    }
    await Future.wait(futures);
  }

  Future<void> _launchInView(
    FlutterDevice device,
    Uri main,
    Uri assetsDirectory,
  ) async {
    final List<FlutterView> views = await device.vmService!.getFlutterViews();
    await Future.wait(<Future<void>>[
      for (final FlutterView view in views)
        device.vmService!.runInView(
          viewId: view.id,
          main: main,
          assetsDirectory: assetsDirectory,
        ),
    ]);
  }

  Future<void> _launchFromDevFS() async {
    final List<Future<void>> futures = <Future<void>>[];
    for (final FlutterDevice? device in flutterDevices) {
      final Uri deviceEntryUri = device!.devFS!.baseUri!.resolve(_swap ? 'main.dart.swap.dill' : 'main.dart.dill');
      final Uri deviceAssetsDirectoryUri = device.devFS!.baseUri!.resolveUri(
        globals.fs.path.toUri(getAssetBuildDirectory()));
      futures.add(_launchInView(device,
                          deviceEntryUri,
                          deviceAssetsDirectoryUri));
    }
    await Future.wait(futures);
  }

  Future<OperationResult> _restartFromSources({
    String? reason,
  }) async {
    final Stopwatch restartTimer = Stopwatch()..start();
    UpdateFSReport updatedDevFS;
    try {
      updatedDevFS = await _updateDevFS(fullRestart: true);
    } finally {
      hotRunnerConfig!.updateDevFSComplete();
    }
    if (!updatedDevFS.success) {
      for (final FlutterDevice? device in flutterDevices) {
        if (device!.generator != null) {
          await device.generator!.reject();
        }
      }
      return OperationResult(1, 'DevFS synchronization failed');
    }
    _resetDirtyAssets();
    for (final FlutterDevice? device in flutterDevices) {
      // VM must have accepted the kernel binary, there will be no reload
      // report, so we let incremental compiler know that source code was accepted.
      if (device!.generator != null) {
        device.generator!.accept();
      }
    }
    // Check if the isolate is paused and resume it.
    final List<Future<void>> operations = <Future<void>>[];
    for (final FlutterDevice? device in flutterDevices) {
      final Set<String?> uiIsolatesIds = <String?>{};
      final List<FlutterView> views = await device!.vmService!.getFlutterViews();
      for (final FlutterView view in views) {
        if (view.uiIsolate == null) {
          continue;
        }
        uiIsolatesIds.add(view.uiIsolate!.id);
        // Reload the isolate.
        final Future<vm_service.Isolate?> reloadIsolate = device.vmService!
          .getIsolateOrNull(view.uiIsolate!.id!);
        operations.add(reloadIsolate.then((vm_service.Isolate? isolate) async {
          if ((isolate != null) && isPauseEvent(isolate.pauseEvent!.kind!)) {
            // The embedder requires that the isolate is unpaused, because the
            // runInView method requires interaction with dart engine APIs that
            // are not thread-safe, and thus must be run on the same thread that
            // would be blocked by the pause. Simply un-pausing is not sufficient,
            // because this does not prevent the isolate from immediately hitting
            // a breakpoint (for example if the breakpoint was placed in a loop
            // or in a frequently called method) or an exception. Instead, all
            // breakpoints are first disabled and exception pause mode set to
            // None, and then the isolate resumed.
            // These settings to not need restoring as Hot Restart results in
            // new isolates, which will be configured by the editor as they are
            // started.
            final List<Future<void>> breakpointAndExceptionRemoval = <Future<void>>[
              device.vmService!.service.setIsolatePauseMode(isolate.id!,
                exceptionPauseMode: vm_service.ExceptionPauseMode.kNone),
              for (final vm_service.Breakpoint breakpoint in isolate.breakpoints!)
                device.vmService!.service.removeBreakpoint(isolate.id!, breakpoint.id!),
            ];
            await Future.wait(breakpointAndExceptionRemoval);
            await device.vmService!.service.resume(view.uiIsolate!.id!);
          }
        }));
      }

      // The engine handles killing and recreating isolates that it has spawned
      // ("uiIsolates"). The isolates that were spawned from these uiIsolates
      // will not be restarted, and so they must be manually killed.
      final vm_service.VM vm = await device.vmService!.service.getVM();
      for (final vm_service.IsolateRef isolateRef in vm.isolates!) {
        if (uiIsolatesIds.contains(isolateRef.id)) {
          continue;
        }
        operations.add(
          device.vmService!.service.kill(isolateRef.id!)
          // Since we never check the value of this Future, only await its
          // completion, make its type nullable so we can return null when
          // catching errors.
          .then<vm_service.Success?>((vm_service.Success success) => success)
          .catchError((dynamic error, StackTrace stackTrace) {
            // Do nothing on a SentinelException since it means the isolate
            // has already been killed.
            // Error code 105 indicates the isolate is not yet runnable, and might
            // be triggered if the tool is attempting to kill the asset parsing
            // isolate before it has finished starting up.
            return null;
          }, test: (dynamic error) => error is vm_service.SentinelException
            || (error is vm_service.RPCError && error.code == 105)));
      }
    }
    await Future.wait(operations);

    await _launchFromDevFS();
    restartTimer.stop();
    globals.printTrace('Hot restart performed in ${getElapsedAsMilliseconds(restartTimer.elapsed)}.');
    _addBenchmarkData('hotRestartMillisecondsToFrame',
        restartTimer.elapsed.inMilliseconds);

    // Send timing analytics.
    globals.flutterUsage.sendTiming('hot', 'restart', restartTimer.elapsed);

    // Toggle the main dill name after successfully uploading.
    _swap =! _swap;

    return OperationResult(
      OperationResult.ok.code,
      OperationResult.ok.message,
      updateFSReport: updatedDevFS,
    );
  }

  /// Returns [true] if the reload was successful.
  /// Prints errors if [printErrors] is [true].
  static bool validateReloadReport(
    vm_service.ReloadReport? reloadReport, {
    bool printErrors = true,
  }) {
    if (reloadReport == null) {
      if (printErrors) {
        globals.printError('Hot reload did not receive reload report.');
      }
      return false;
    }
    final ReloadReportContents contents = ReloadReportContents.fromReloadReport(reloadReport);
    if (!reloadReport.success!) {
      if (printErrors) {
        globals.printError('Hot reload was rejected:');
        for (final ReasonForCancelling reason in contents.notices) {
          globals.printError(reason.toString());
        }
      }
      return false;
    }
    return true;
  }

  @override
  Future<OperationResult> restart({
    bool fullRestart = false,
    String? reason,
    bool silent = false,
    bool pause = false,
  }) async {
    if (flutterDevices.any((FlutterDevice? device) => device!.devFS == null)) {
      return OperationResult(1, 'Device initialization has not completed.');
    }
    await _calculateTargetPlatform();
    final Stopwatch timer = Stopwatch()..start();

    // Run source generation if needed.
    await runSourceGenerators();

    if (fullRestart) {
      final OperationResult result = await _fullRestartHelper(
        targetPlatform: _targetPlatform,
        sdkName: _sdkName,
        emulator: _emulator,
        reason: reason,
        silent: silent,
      );
      if (!silent) {
        globals.printStatus('Restarted application in ${getElapsedAsMilliseconds(timer.elapsed)}.');
      }
      unawaited(residentDevtoolsHandler!.hotRestart(flutterDevices));
      return result;
    }
    final OperationResult result = await _hotReloadHelper(
      targetPlatform: _targetPlatform,
      sdkName: _sdkName,
      emulator: _emulator,
      reason: reason,
      pause: pause,
    );
    if (result.isOk) {
      final String elapsed = getElapsedAsMilliseconds(timer.elapsed);
      if (!silent) {
        if (result.extraTimings.isNotEmpty) {
          final String extraTimingsString = result.extraTimings
            .map((OperationResultExtraTiming e) => '${e.description}: ${e.timeInMs} ms')
            .join(', ');
          globals.printStatus('${result.message} in $elapsed ($extraTimingsString).');
        } else {
          globals.printStatus('${result.message} in $elapsed.');
        }
      }
    }
    return result;
  }

  Future<OperationResult> _fullRestartHelper({
    String? targetPlatform,
    String? sdkName,
    bool? emulator,
    String? reason,
    bool? silent,
  }) async {
    if (!supportsRestart) {
      return OperationResult(1, 'hotRestart not supported');
    }
    Status? status;
    if (!silent!) {
      status = globals.logger.startProgress(
        'Performing hot restart...',
        progressId: 'hot.restart',
      );
    }
    OperationResult result;
    String? restartEvent;
    try {
      final Stopwatch restartTimer = _stopwatchFactory.createStopwatch('fullRestartHelper')..start();
      if ((await hotRunnerConfig!.setupHotRestart()) != true) {
        return OperationResult(1, 'setupHotRestart failed');
      }
      result = await _restartFromSources(reason: reason);
      restartTimer.stop();
      if (!result.isOk) {
        restartEvent = 'restart-failed';
      } else {
        HotEvent('restart',
          targetPlatform: targetPlatform!,
          sdkName: sdkName!,
          emulator: emulator!,
          fullRestart: true,
          reason: reason,
          fastReassemble: false,
          overallTimeInMs: restartTimer.elapsed.inMilliseconds,
          syncedBytes: result.updateFSReport?.syncedBytes,
          invalidatedSourcesCount: result.updateFSReport?.invalidatedSourcesCount,
          transferTimeInMs: result.updateFSReport?.transferDuration.inMilliseconds,
          compileTimeInMs: result.updateFSReport?.compileDuration.inMilliseconds,
          findInvalidatedTimeInMs: result.updateFSReport?.findInvalidatedDuration.inMilliseconds,
          scannedSourcesCount: result.updateFSReport?.scannedSourcesCount,
        ).send();
      }
    } on vm_service.SentinelException catch (err, st) {
      restartEvent = 'exception';
      return OperationResult(1, 'hot restart failed to complete: $err\n$st', fatal: true);
    } on vm_service.RPCError  catch (err, st) {
      restartEvent = 'exception';
      return OperationResult(1, 'hot restart failed to complete: $err\n$st', fatal: true);
    } finally {
      // The `restartEvent` variable will be null if restart succeeded. We will
      // only handle the case when it failed here.
      if (restartEvent != null) {
        HotEvent(restartEvent,
          targetPlatform: targetPlatform!,
          sdkName: sdkName!,
          emulator: emulator!,
          fullRestart: true,
          reason: reason,
          fastReassemble: false,
        ).send();
      }
      status?.cancel();
    }
    return result;
  }

  Future<OperationResult> _hotReloadHelper({
    String? targetPlatform,
    String? sdkName,
    bool? emulator,
    String? reason,
    bool? pause,
  }) async {
    Status status = globals.logger.startProgress(
      'Performing hot reload...',
      progressId: 'hot.reload',
    );
    OperationResult result;
    try {
      result = await _reloadSources(
        targetPlatform: targetPlatform,
        sdkName: sdkName,
        emulator: emulator,
        reason: reason,
        pause: pause,
        onSlow: (String message) {
          status.cancel();
          status = globals.logger.startProgress(
            message,
            progressId: 'hot.reload',
          );
        },
      );
    } on vm_service.RPCError catch (error) {
      String errorMessage = 'hot reload failed to complete';
      int errorCode = 1;
      if (error.code == kIsolateReloadBarred) {
        errorCode = error.code;
        errorMessage = 'Unable to hot reload application due to an unrecoverable error in '
                      'the source code. Please address the error and then use "R" to '
                      'restart the app.\n'
                      '${error.message} (error code: ${error.code})';
        HotEvent('reload-barred',
          targetPlatform: targetPlatform!,
          sdkName: sdkName!,
          emulator: emulator!,
          fullRestart: false,
          reason: reason,
          fastReassemble: false,
        ).send();
      } else {
        HotEvent('exception',
          targetPlatform: targetPlatform!,
          sdkName: sdkName!,
          emulator: emulator!,
          fullRestart: false,
          reason: reason,
          fastReassemble: false,
        ).send();
      }
      return OperationResult(errorCode, errorMessage, fatal: true);
    } finally {
      status.cancel();
    }
    return result;
  }

  Future<OperationResult> _reloadSources({
    String? targetPlatform,
    String? sdkName,
    bool? emulator,
    bool? pause = false,
    String? reason,
    void Function(String message)? onSlow,
  }) async {
    final Map<FlutterDevice?, List<FlutterView>> viewCache = <FlutterDevice?, List<FlutterView>>{};
    for (final FlutterDevice? device in flutterDevices) {
      final List<FlutterView> views = await device!.vmService!.getFlutterViews();
      viewCache[device] = views;
      for (final FlutterView view in views) {
        if (view.uiIsolate == null) {
          return OperationResult(2, 'Application isolate not found', fatal: true);
        }
      }
    }

    final Stopwatch reloadTimer = _stopwatchFactory.createStopwatch('reloadSources:reload')..start();
    if ((await hotRunnerConfig!.setupHotReload()) != true) {
      return OperationResult(1, 'setupHotReload failed');
    }
    final Stopwatch devFSTimer = Stopwatch()..start();
    UpdateFSReport updatedDevFS;
    try {
      updatedDevFS= await _updateDevFS();
    } finally {
      hotRunnerConfig!.updateDevFSComplete();
    }
    // Record time it took to synchronize to DevFS.
    bool shouldReportReloadTime = true;
    _addBenchmarkData('hotReloadDevFSSyncMilliseconds', devFSTimer.elapsed.inMilliseconds);
    if (!updatedDevFS.success) {
      return OperationResult(1, 'DevFS synchronization failed');
    }

    final List<OperationResultExtraTiming> extraTimings = <OperationResultExtraTiming>[];
    extraTimings.add(OperationResultExtraTiming('compile', updatedDevFS.compileDuration.inMilliseconds));

    String reloadMessage = 'Reloaded 0 libraries';
    final Stopwatch reloadVMTimer = _stopwatchFactory.createStopwatch('reloadSources:vm')..start();
    final Map<String, Object?> firstReloadDetails = <String, Object?>{};
    if (updatedDevFS.invalidatedSourcesCount > 0) {
      final OperationResult result = await _reloadSourcesHelper(
        this,
        flutterDevices,
        pause,
        firstReloadDetails,
        targetPlatform,
        sdkName,
        emulator,
        reason,
      );
      if (result.code != 0) {
        return result;
      }
      reloadMessage = result.message;
    } else {
      _addBenchmarkData('hotReloadVMReloadMilliseconds', 0);
    }
    reloadVMTimer.stop();
    extraTimings.add(OperationResultExtraTiming('reload', reloadVMTimer.elapsedMilliseconds));

    await evictDirtyAssets();

    final Stopwatch reassembleTimer = _stopwatchFactory.createStopwatch('reloadSources:reassemble')..start();

    final ReassembleResult reassembleResult = await _reassembleHelper(
      flutterDevices,
      viewCache,
      onSlow,
      reloadMessage,
      updatedDevFS.fastReassembleClassName,
    );
    shouldReportReloadTime = reassembleResult.shouldReportReloadTime;
    if (reassembleResult.reassembleViews.isEmpty) {
      return OperationResult(OperationResult.ok.code, reloadMessage);
    }
    // Record time it took for Flutter to reassemble the application.
    reassembleTimer.stop();
    _addBenchmarkData('hotReloadFlutterReassembleMilliseconds', reassembleTimer.elapsed.inMilliseconds);
    extraTimings.add(OperationResultExtraTiming('reassemble', reassembleTimer.elapsedMilliseconds));

    reloadTimer.stop();
    final Duration reloadDuration = reloadTimer.elapsed;
    final int reloadInMs = reloadDuration.inMilliseconds;

    // Collect stats that help understand scale of update for this hot reload request.
    // For example, [syncedLibraryCount]/[finalLibraryCount] indicates how
    // many libraries were affected by the hot reload request.
    // Relation of [invalidatedSourcesCount] to [syncedLibraryCount] should help
    // understand sync/transfer "overhead" of updating this number of source files.
    HotEvent('reload',
      targetPlatform: targetPlatform!,
      sdkName: sdkName!,
      emulator: emulator!,
      fullRestart: false,
      reason: reason,
      overallTimeInMs: reloadInMs,
      finalLibraryCount: firstReloadDetails['finalLibraryCount'] as int? ?? 0,
      syncedLibraryCount: firstReloadDetails['receivedLibraryCount'] as int? ?? 0,
      syncedClassesCount: firstReloadDetails['receivedClassesCount'] as int? ?? 0,
      syncedProceduresCount: firstReloadDetails['receivedProceduresCount'] as int? ?? 0,
      syncedBytes: updatedDevFS.syncedBytes,
      invalidatedSourcesCount: updatedDevFS.invalidatedSourcesCount,
      transferTimeInMs: updatedDevFS.transferDuration.inMilliseconds,
      fastReassemble: featureFlags.isSingleWidgetReloadEnabled && updatedDevFS.fastReassembleClassName != null,
      compileTimeInMs: updatedDevFS.compileDuration.inMilliseconds,
      findInvalidatedTimeInMs: updatedDevFS.findInvalidatedDuration.inMilliseconds,
      scannedSourcesCount: updatedDevFS.scannedSourcesCount,
      reassembleTimeInMs: reassembleTimer.elapsed.inMilliseconds,
      reloadVMTimeInMs: reloadVMTimer.elapsed.inMilliseconds,
    ).send();

    if (shouldReportReloadTime) {
      globals.printTrace('Hot reload performed in ${getElapsedAsMilliseconds(reloadDuration)}.');
      // Record complete time it took for the reload.
      _addBenchmarkData('hotReloadMillisecondsToFrame', reloadInMs);
    }
    // Only report timings if we reloaded a single view without any errors.
    if ((reassembleResult.reassembleViews.length == 1) && !reassembleResult.failedReassemble && shouldReportReloadTime) {
      globals.flutterUsage.sendTiming('hot', 'reload', reloadDuration);
    }
    return OperationResult(
      reassembleResult.failedReassemble ? 1 : OperationResult.ok.code,
      reloadMessage,
      extraTimings: extraTimings
    );
  }

  @override
  void printHelp({ required bool details }) {
    globals.printStatus('Flutter run key commands.');
    commandHelp.r.print();
    if (supportsRestart) {
      commandHelp.R.print();
    }
    if (details) {
      printHelpDetails();
      commandHelp.hWithDetails.print();
    } else {
      commandHelp.hWithoutDetails.print();
    }
    if (_didAttach) {
      commandHelp.d.print();
    }
    commandHelp.c.print();
    commandHelp.q.print();
    globals.printStatus('');
    if (debuggingOptions.buildInfo.nullSafetyMode ==  NullSafetyMode.sound) {
      globals.printStatus('💪 Running with sound null safety 💪', emphasis: true);
    } else {
      globals.printStatus(
        'Running without sound null safety ⚠️',
        emphasis: true,
      );
      globals.printStatus(
        'Dart 3 will only support sound null safety, see https://dart.dev/null-safety',
      );
    }
    globals.printStatus('');
    printDebuggerList();
  }

  @visibleForTesting
  Future<void> evictDirtyAssets() async {
    final List<Future<void>> futures = <Future<void>>[];
    for (final FlutterDevice? device in flutterDevices) {
      if (device!.devFS!.assetPathsToEvict.isEmpty &&
          device.devFS!.shaderPathsToEvict.isEmpty &&
          device.devFS!.scenePathsToEvict.isEmpty) {
        continue;
      }
      final List<FlutterView> views = await device.vmService!.getFlutterViews();

      // If this is the first time we update the assets, make sure to call the setAssetDirectory
      if (!device.devFS!.hasSetAssetDirectory) {
        final Uri deviceAssetsDirectoryUri = device.devFS!.baseUri!.resolveUri(globals.fs.path.toUri(getAssetBuildDirectory()));
        await Future.wait<void>(views.map<Future<void>>(
          (FlutterView view) => device.vmService!.setAssetDirectory(
            assetsDirectory: deviceAssetsDirectoryUri,
            uiIsolateId: view.uiIsolate!.id,
            viewId: view.id,
            windows: device.targetPlatform == TargetPlatform.windows_x64,
          )
        ));
        for (final FlutterView view in views) {
          globals.printTrace('Set asset directory in $view.');
        }
        device.devFS!.hasSetAssetDirectory = true;
      }

      if (views.first.uiIsolate == null) {
        globals.printError('Application isolate not found for $device');
        continue;
      }

      if (device.devFS!.didUpdateFontManifest) {
        futures.add(device.vmService!.reloadAssetFonts(
            isolateId: views.first.uiIsolate!.id!,
            viewId: views.first.id,
        ));
      }

      for (final String assetPath in device.devFS!.assetPathsToEvict) {
        futures.add(
          device.vmService!
            .flutterEvictAsset(
              assetPath,
              isolateId: views.first.uiIsolate!.id!,
            )
        );
      }
      for (final String assetPath in device.devFS!.shaderPathsToEvict) {
        futures.add(
          device.vmService!
            .flutterEvictShader(
              assetPath,
              isolateId: views.first.uiIsolate!.id!,
            )
        );
      }
      for (final String assetPath in device.devFS!.scenePathsToEvict) {
        futures.add(
          device.vmService!
            .flutterEvictScene(
              assetPath,
              isolateId: views.first.uiIsolate!.id!,
            )
        );
      }
      device.devFS!.assetPathsToEvict.clear();
      device.devFS!.shaderPathsToEvict.clear();
      device.devFS!.scenePathsToEvict.clear();
    }
    await Future.wait<void>(futures);
  }

  @override
  Future<void> cleanupAfterSignal() async {
    await stopEchoingDeviceLog();
    await hotRunnerConfig!.runPreShutdownOperations();
    if (_didAttach) {
      appFinished();
    } else {
      await exitApp();
    }
  }

  @override
  Future<void> preExit() async {
    await _cleanupDevFS();
    await hotRunnerConfig!.runPreShutdownOperations();
    await super.preExit();
  }

  @override
  Future<void> cleanupAtFinish() async {
    for (final FlutterDevice? flutterDevice in flutterDevices) {
      await flutterDevice!.device!.dispose();
    }
    await _cleanupDevFS();
    await residentDevtoolsHandler!.shutdown();
    await stopEchoingDeviceLog();
  }
}

typedef ReloadSourcesHelper = Future<OperationResult> Function(
  HotRunner hotRunner,
  List<FlutterDevice?> flutterDevices,
  bool? pause,
  Map<String, dynamic> firstReloadDetails,
  String? targetPlatform,
  String? sdkName,
  bool? emulator,
  String? reason,
);

Future<OperationResult> _defaultReloadSourcesHelper(
  HotRunner hotRunner,
  List<FlutterDevice?> flutterDevices,
  bool? pause,
  Map<String, dynamic> firstReloadDetails,
  String? targetPlatform,
  String? sdkName,
  bool? emulator,
  String? reason,
) async {
  final Stopwatch vmReloadTimer = Stopwatch()..start();
  const String entryPath = 'main.dart.incremental.dill';
  final List<Future<DeviceReloadReport>> allReportsFutures = <Future<DeviceReloadReport>>[];

  for (final FlutterDevice? device in flutterDevices) {
    final List<Future<vm_service.ReloadReport>> reportFutures = await _reloadDeviceSources(
      device!,
      entryPath,
      pause: pause,
    );
    allReportsFutures.add(Future.wait(reportFutures).then(
      (List<vm_service.ReloadReport> reports) async {
        // TODO(aam): Investigate why we are validating only first reload report,
        // which seems to be current behavior
        final vm_service.ReloadReport firstReport = reports.first;
        // Don't print errors because they will be printed further down when
        // `validateReloadReport` is called again.
        await device.updateReloadStatus(
          HotRunner.validateReloadReport(firstReport, printErrors: false),
        );
        return DeviceReloadReport(device, reports);
      },
    ));
  }
  final List<DeviceReloadReport> reports = await Future.wait(allReportsFutures);
  final vm_service.ReloadReport reloadReport = reports.first.reports[0];
  if (!HotRunner.validateReloadReport(reloadReport)) {
    // Reload failed.
    HotEvent('reload-reject',
      targetPlatform: targetPlatform!,
      sdkName: sdkName!,
      emulator: emulator!,
      fullRestart: false,
      reason: reason,
      fastReassemble: false,
    ).send();
    // Reset devFS lastCompileTime to ensure the file will still be marked
    // as dirty on subsequent reloads.
    _resetDevFSCompileTime(flutterDevices);
    final ReloadReportContents contents = ReloadReportContents.fromReloadReport(reloadReport);
    return OperationResult(1, 'Reload rejected: ${contents.notices.join("\n")}');
  }
  // Collect stats only from the first device. If/when run -d all is
  // refactored, we'll probably need to send one hot reload/restart event
  // per device to analytics.
  firstReloadDetails.addAll(castStringKeyedMap(reloadReport.json!['details'])!);
  final Map<String, dynamic> details = reloadReport.json!['details'] as Map<String, dynamic>;
  final int? loadedLibraryCount = details['loadedLibraryCount'] as int?;
  final int? finalLibraryCount = details['finalLibraryCount'] as int?;
  globals.printTrace('reloaded $loadedLibraryCount of $finalLibraryCount libraries');
  // reloadMessage = 'Reloaded $loadedLibraryCount of $finalLibraryCount libraries';
  // Record time it took for the VM to reload the sources.
  hotRunner._addBenchmarkData('hotReloadVMReloadMilliseconds', vmReloadTimer.elapsed.inMilliseconds);
  return OperationResult(0, 'Reloaded $loadedLibraryCount of $finalLibraryCount libraries');
}

Future<List<Future<vm_service.ReloadReport>>> _reloadDeviceSources(
  FlutterDevice device,
  String entryPath, {
  bool? pause = false,
}) async {
  final String deviceEntryUri = device.devFS!.baseUri!
    .resolve(entryPath).toString();
  final vm_service.VM vm = await device.vmService!.service.getVM();
  return <Future<vm_service.ReloadReport>>[
    for (final vm_service.IsolateRef isolateRef in vm.isolates!)
      device.vmService!.service.reloadSources(
        isolateRef.id!,
        pause: pause,
        rootLibUri: deviceEntryUri,
      ),
  ];
}

void _resetDevFSCompileTime(List<FlutterDevice?> flutterDevices) {
  for (final FlutterDevice? device in flutterDevices) {
    device!.devFS!.resetLastCompiled();
  }
}

@visibleForTesting
class ReassembleResult {
  ReassembleResult(this.reassembleViews, this.failedReassemble, this.shouldReportReloadTime);
  final Map<FlutterView?, FlutterVmService?> reassembleViews;
  final bool failedReassemble;
  final bool shouldReportReloadTime;
}

typedef ReassembleHelper = Future<ReassembleResult> Function(
  List<FlutterDevice?> flutterDevices,
  Map<FlutterDevice?, List<FlutterView>> viewCache,
  void Function(String message)? onSlow,
  String reloadMessage,
  String? fastReassembleClassName,
);

Future<ReassembleResult> _defaultReassembleHelper(
  List<FlutterDevice?> flutterDevices,
  Map<FlutterDevice?, List<FlutterView>> viewCache,
  void Function(String message)? onSlow,
  String reloadMessage,
  String? fastReassembleClassName,
) async {
  // Check if any isolates are paused and reassemble those that aren't.
  final Map<FlutterView, FlutterVmService?> reassembleViews = <FlutterView, FlutterVmService?>{};
  final List<Future<void>> reassembleFutures = <Future<void>>[];
  String? serviceEventKind;
  int pausedIsolatesFound = 0;
  bool failedReassemble = false;
  bool shouldReportReloadTime = true;
  for (final FlutterDevice? device in flutterDevices) {
    final List<FlutterView> views = viewCache[device]!;
    for (final FlutterView view in views) {
      // Check if the isolate is paused, and if so, don't reassemble. Ignore the
      // PostPauseEvent event - the client requesting the pause will resume the app.
      final vm_service.Isolate? isolate = await device!.vmService!
        .getIsolateOrNull(view.uiIsolate!.id!);
      final vm_service.Event? pauseEvent = isolate?.pauseEvent;
      if (pauseEvent != null
        && isPauseEvent(pauseEvent.kind!)
        && pauseEvent.kind != vm_service.EventKind.kPausePostRequest) {
        pausedIsolatesFound += 1;
        if (serviceEventKind == null) {
          serviceEventKind = pauseEvent.kind;
        } else if (serviceEventKind != pauseEvent.kind) {
          serviceEventKind = ''; // many kinds
        }
      } else {
        reassembleViews[view] = device.vmService;
        // If the tool identified a change in a single widget, do a fast instead
        // of a full reassemble.
        Future<void> reassembleWork;
        if (fastReassembleClassName != null) {
          reassembleWork = device.vmService!.flutterFastReassemble(
            isolateId: view.uiIsolate!.id!,
            className: fastReassembleClassName,
          );
        } else {
          reassembleWork = device.vmService!.flutterReassemble(
            isolateId: view.uiIsolate!.id!,
          );
        }
        reassembleFutures.add(reassembleWork.catchError((dynamic error) {
          failedReassemble = true;
          globals.printError('Reassembling ${view.uiIsolate!.name} failed: $error');
        }, test: (dynamic error) => error is Exception));
      }
    }
  }
  if (pausedIsolatesFound > 0) {
    if (onSlow != null) {
      onSlow('${_describePausedIsolates(pausedIsolatesFound, serviceEventKind!)}; interface might not update.');
    }
    if (reassembleViews.isEmpty) {
      globals.printTrace('Skipping reassemble because all isolates are paused.');
      return ReassembleResult(reassembleViews, failedReassemble, shouldReportReloadTime);
    }
  }
  assert(reassembleViews.isNotEmpty);

  globals.printTrace('Reassembling application');

  final Future<void> reassembleFuture = Future.wait<void>(reassembleFutures).then((void _) => null);
  await reassembleFuture.timeout(
    const Duration(seconds: 2),
    onTimeout: () async {
      if (pausedIsolatesFound > 0) {
        shouldReportReloadTime = false;
        return ; // probably no point waiting, they're probably deadlocked and we've already warned.
      }
      // Check if any isolate is newly paused.
      globals.printTrace('This is taking a long time; will now check for paused isolates.');
      int postReloadPausedIsolatesFound = 0;
      String? serviceEventKind;
      for (final FlutterView view in reassembleViews.keys) {
        final vm_service.Isolate? isolate = await reassembleViews[view]!
          .getIsolateOrNull(view.uiIsolate!.id!);
        if (isolate == null) {
          continue;
        }
        if (isolate.pauseEvent != null && isPauseEvent(isolate.pauseEvent!.kind!)) {
          postReloadPausedIsolatesFound += 1;
          if (serviceEventKind == null) {
            serviceEventKind = isolate.pauseEvent!.kind;
          } else if (serviceEventKind != isolate.pauseEvent!.kind) {
            serviceEventKind = ''; // many kinds
          }
        }
      }
      globals.printTrace('Found $postReloadPausedIsolatesFound newly paused isolate(s).');
      if (postReloadPausedIsolatesFound == 0) {
        await reassembleFuture; // must just be taking a long time... keep waiting!
        return;
      }
      shouldReportReloadTime = false;
      if (onSlow != null) {
        onSlow('${_describePausedIsolates(postReloadPausedIsolatesFound, serviceEventKind!)}.');
      }
      return;
    },
  );
  return ReassembleResult(reassembleViews, failedReassemble, shouldReportReloadTime);
}

String _describePausedIsolates(int pausedIsolatesFound, String serviceEventKind) {
  assert(pausedIsolatesFound > 0);
  final StringBuffer message = StringBuffer();
  bool plural;
  if (pausedIsolatesFound == 1) {
    message.write('The application is ');
    plural = false;
  } else {
    message.write('$pausedIsolatesFound isolates are ');
    plural = true;
  }
  switch (serviceEventKind) {
    case vm_service.EventKind.kPauseStart:
      message.write('paused (probably due to --start-paused)');
      break;
    case vm_service.EventKind.kPauseExit:
      message.write('paused because ${ plural ? 'they have' : 'it has' } terminated');
      break;
    case vm_service.EventKind.kPauseBreakpoint:
      message.write('paused in the debugger on a breakpoint');
      break;
    case vm_service.EventKind.kPauseInterrupted:
      message.write('paused due in the debugger');
      break;
    case vm_service.EventKind.kPauseException:
      message.write('paused in the debugger after an exception was thrown');
      break;
    case vm_service.EventKind.kPausePostRequest:
      message.write('paused');
      break;
    case '':
      message.write('paused for various reasons');
      break;
    default:
      message.write('paused');
  }
  return message.toString();
}

/// The result of an invalidation check from [ProjectFileInvalidator].
class InvalidationResult {
  const InvalidationResult({
    this.uris,
    this.packageConfig,
  });

  final List<Uri>? uris;
  final PackageConfig? packageConfig;
}

/// The [ProjectFileInvalidator] track the dependencies for a running
/// application to determine when they are dirty.
class ProjectFileInvalidator {
  ProjectFileInvalidator({
    required FileSystem fileSystem,
    required Platform platform,
    required Logger logger,
  }): _fileSystem = fileSystem,
      _platform = platform,
      _logger = logger;

  final FileSystem _fileSystem;
  final Platform _platform;
  final Logger _logger;

  static const String _pubCachePathLinuxAndMac = '.pub-cache';
  static const String _pubCachePathWindows = 'Pub/Cache';

  // As of writing, Dart supports up to 32 asynchronous I/O threads per
  // isolate. We also want to avoid hitting platform limits on open file
  // handles/descriptors.
  //
  // This value was chosen based on empirical tests scanning a set of
  // ~2000 files.
  static const int _kMaxPendingStats = 8;

  Future<InvalidationResult> findInvalidated({
    required DateTime? lastCompiled,
    required List<Uri> urisToMonitor,
    required String packagesPath,
    required PackageConfig packageConfig,
    bool asyncScanning = false,
  }) async {

    if (lastCompiled == null) {
      // Initial load.
      assert(urisToMonitor.isEmpty);
      return InvalidationResult(
        packageConfig: packageConfig,
        uris: <Uri>[],
      );
    }

    final Stopwatch stopwatch = Stopwatch()..start();
    final List<Uri> urisToScan = <Uri>[
      // Don't watch pub cache directories to speed things up a little.
      for (final Uri uri in urisToMonitor)
        if (_isNotInPubCache(uri)) uri,
    ];
    final List<Uri> invalidatedFiles = <Uri>[];
    if (asyncScanning) {
      final Pool pool = Pool(_kMaxPendingStats);
      final List<Future<void>> waitList = <Future<void>>[];
      for (final Uri uri in urisToScan) {
        waitList.add(pool.withResource<void>(
          // Calling fs.stat() is more performant than fs.file().stat(), but
          // uri.toFilePath() does not work with MultiRootFileSystem.
          () => (uri.hasScheme && uri.scheme != 'file'
            ? _fileSystem.file(uri).stat()
            :  _fileSystem.stat(uri.toFilePath(windows: _platform.isWindows)))
            .then((FileStat stat) {
              final DateTime updatedAt = stat.modified;
              if (updatedAt.isAfter(lastCompiled)) {
                invalidatedFiles.add(uri);
              }
            })
        ));
      }
      await Future.wait<void>(waitList);
    } else {
      for (final Uri uri in urisToScan) {
        // Calling fs.statSync() is more performant than fs.file().statSync(), but
        // uri.toFilePath() does not work with MultiRootFileSystem.
        final DateTime updatedAt = uri.hasScheme && uri.scheme != 'file'
          ? _fileSystem.file(uri).statSync().modified
          : _fileSystem.statSync(uri.toFilePath(windows: _platform.isWindows)).modified;
        if (updatedAt.isAfter(lastCompiled)) {
          invalidatedFiles.add(uri);
        }
      }
    }
    // We need to check the .packages file too since it is not used in compilation.
    final File packageFile = _fileSystem.file(packagesPath);
    final Uri packageUri = packageFile.uri;
    final DateTime updatedAt = packageFile.statSync().modified;
    if (updatedAt.isAfter(lastCompiled)) {
      invalidatedFiles.add(packageUri);
      packageConfig = await _createPackageConfig(packagesPath);
      // The frontend_server might be monitoring the package_config.json file,
      // Pub should always produce both files.
      // TODO(zanderso): remove after https://github.com/flutter/flutter/issues/55249
      if (_fileSystem.path.basename(packagesPath) == '.packages') {
        final File packageConfigFile = _fileSystem.file(packagesPath)
          .parent.childDirectory('.dart_tool')
          .childFile('package_config.json');
        if (packageConfigFile.existsSync()) {
          invalidatedFiles.add(packageConfigFile.uri);
        }
      }
    }

    _logger.printTrace(
      'Scanned through ${urisToScan.length} files in '
      '${stopwatch.elapsedMilliseconds}ms'
      '${asyncScanning ? " (async)" : ""}',
    );
    return InvalidationResult(
      packageConfig: packageConfig,
      uris: invalidatedFiles,
    );
  }

  bool _isNotInPubCache(Uri uri) {
    return !(_platform.isWindows && uri.path.contains(_pubCachePathWindows))
        && !uri.path.contains(_pubCachePathLinuxAndMac);
  }

  Future<PackageConfig> _createPackageConfig(String packagesPath) {
    return loadPackageConfigWithLogging(
      _fileSystem.file(packagesPath),
      logger: _logger,
    );
  }
}

/// Additional serialization logic for a hot reload response.
class ReloadReportContents {
  factory ReloadReportContents.fromReloadReport(vm_service.ReloadReport report) {
    final List<ReasonForCancelling> reasons = <ReasonForCancelling>[];
    final Object? notices = report.json!['notices'];
    if (notices is! List<dynamic>) {
      return ReloadReportContents._(report.success, reasons, report);
    }
    for (final Object? obj in notices) {
      if (obj is! Map<String, dynamic>) {
        continue;
      }
      final Map<String, dynamic> notice = obj;
      reasons.add(ReasonForCancelling(
        message: notice['message'] is String
          ? notice['message'] as String?
          : 'Unknown Error',
      ));
    }

    return ReloadReportContents._(report.success, reasons, report);
  }

  ReloadReportContents._(
    this.success,
    this.notices,
    this.report,
  );

  final bool? success;
  final List<ReasonForCancelling> notices;
  final vm_service.ReloadReport report;
}

/// A serialization class for hot reload rejection reasons.
///
/// Injects an additional error message that a hot restart will
/// resolve the issue.
class ReasonForCancelling {
  ReasonForCancelling({
    this.message,
  });

  final String? message;

  @override
  String toString() {
    return '$message.\nTry performing a hot restart instead.';
  }
}
