// 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:build_daemon/client.dart';
import 'package:dwds/dwds.dart';
import 'package:meta/meta.dart';
import 'package:vm_service/vm_service.dart' as vmservice;
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
    hide StackTrace;

import '../application_package.dart';
import '../base/async_guard.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../base/terminal.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../convert.dart';
import '../devfs.dart';
import '../device.dart';
import '../features.dart';
import '../globals.dart';
import '../project.dart';
import '../reporting/reporting.dart';
import '../resident_runner.dart';
import '../run_hot.dart';
import '../web/chrome.dart';
import '../web/devfs_web.dart';
import '../web/web_device.dart';
import '../web/web_runner.dart';
import 'web_fs.dart';

/// Injectable factory to create a [ResidentWebRunner].
class DwdsWebRunnerFactory extends WebRunnerFactory {
  @override
  ResidentRunner createWebRunner(
    FlutterDevice device, {
    String target,
    @required bool stayResident,
    @required FlutterProject flutterProject,
    @required bool ipv6,
    @required DebuggingOptions debuggingOptions,
    @required List<String> dartDefines,
  }) {
    if (featureFlags.isWebIncrementalCompilerEnabled && debuggingOptions.buildInfo.isDebug) {
      return _ExperimentalResidentWebRunner(
        device,
        target: target,
        flutterProject: flutterProject,
        debuggingOptions: debuggingOptions,
        ipv6: ipv6,
        stayResident: stayResident,
        dartDefines: dartDefines,
      );
    }
    return _DwdsResidentWebRunner(
      device,
      target: target,
      flutterProject: flutterProject,
      debuggingOptions: debuggingOptions,
      ipv6: ipv6,
      stayResident: stayResident,
      dartDefines: dartDefines,
    );
  }
}

/// A hot-runner which handles browser specific delegation.
abstract class ResidentWebRunner extends ResidentRunner {
  ResidentWebRunner(
    this.device, {
    String target,
    @required this.flutterProject,
    @required bool ipv6,
    @required DebuggingOptions debuggingOptions,
    bool stayResident = true,
    @required this.dartDefines,
  }) : super(
          <FlutterDevice>[],
          target: target ?? fs.path.join('lib', 'main.dart'),
          debuggingOptions: debuggingOptions,
          ipv6: ipv6,
          stayResident: stayResident,
        );

  final FlutterDevice device;
  final FlutterProject flutterProject;
  final List<String> dartDefines;
  DateTime firstBuildTime;

  // Only the debug builds of the web support the service protocol.
  @override
  bool get supportsServiceProtocol => isRunningDebug && deviceIsDebuggable;

  @override
  bool get debuggingEnabled => isRunningDebug && deviceIsDebuggable;

  /// WebServer device is debuggable when running with --start-paused.
  bool get deviceIsDebuggable => device.device is! WebServerDevice || debuggingOptions.startPaused;

  bool get _enableDwds => debuggingEnabled;

  WebFs _webFs;
  ConnectionResult _connectionResult;
  StreamSubscription<vmservice.Event> _stdOutSub;
  bool _exited = false;
  WipConnection _wipConnection;

  vmservice.VmService get _vmService =>
      _connectionResult?.debugConnection?.vmService;

  @override
  bool get canHotRestart {
    return true;
  }

  @override
  Future<Map<String, dynamic>> invokeFlutterExtensionRpcRawOnFirstIsolate(
    String method, {
    Map<String, dynamic> params,
  }) async {
    final vmservice.Response response =
        await _vmService.callServiceExtension(method, args: params);
    return response.toJson();
  }

  @override
  Future<void> cleanupAfterSignal() async {
    await _cleanup();
  }

  @override
  Future<void> cleanupAtFinish() async {
    await _cleanup();
  }

  Future<void> _cleanup() async {
    if (_exited) {
      return;
    }
    await _stdOutSub?.cancel();
    await _webFs?.stop();
    await device.device.stopApp(null);
    if (ChromeLauncher.hasChromeInstance) {
      final Chrome chrome = await ChromeLauncher.connectedInstance;
      await chrome.close();
    }
    _exited = true;
  }

  Future<void> _cleanupAndExit() async {
    await _cleanup();
    appFinished();
  }

  @override
  void printHelp({bool details = true}) {
    if (details) {
      return printHelpDetails();
    }
    const String fire = '🔥';
    const String rawMessage =
        '  To hot restart changes while running, press "r". '
        'To hot restart (and refresh the browser), press "R".';
    final String message = terminal.color(
      fire + terminal.bolden(rawMessage),
      TerminalColor.red,
    );
    printStatus(
        'Warning: Flutter\'s support for web development is not stable yet and hasn\'t');
    printStatus('been thoroughly tested in production environments.');
    printStatus('For more information see https://flutter.dev/web');
    printStatus('');
    printStatus(message);
    const String quitMessage = 'To quit, press "q".';
    printStatus('For a more detailed help message, press "h". $quitMessage');
  }

  @override
  Future<void> debugDumpApp() async {
    try {
      await _vmService?.callServiceExtension(
        'ext.flutter.debugDumpApp',
      );
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugDumpRenderTree() async {
    try {
      await _vmService?.callServiceExtension(
        'ext.flutter.debugDumpRenderTree',
      );
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugDumpLayerTree() async {
    try {
      await _vmService?.callServiceExtension(
        'ext.flutter.debugDumpLayerTree',
      );
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugDumpSemanticsTreeInTraversalOrder() async {
    try {
      await _vmService?.callServiceExtension(
          'ext.flutter.debugDumpSemanticsTreeInTraversalOrder');
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugTogglePlatform() async {
    try {
      final vmservice.Response response = await _vmService
          ?.callServiceExtension('ext.flutter.platformOverride');
      final String currentPlatform = response.json['value'] as String;
      String nextPlatform;
      switch (currentPlatform) {
        case 'android':
          nextPlatform = 'iOS';
          break;
        case 'iOS':
          nextPlatform = 'android';
          break;
      }
      if (nextPlatform == null) {
        return;
      }
      await _vmService?.callServiceExtension('ext.flutter.platformOverride',
          args: <String, Object>{
            'value': nextPlatform,
          });
      printStatus('Switched operating system to $nextPlatform');
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugDumpSemanticsTreeInInverseHitTestOrder() async {
    try {
      await _vmService?.callServiceExtension(
          'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder');
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugToggleDebugPaintSizeEnabled() async {
    try {
      final vmservice.Response response =
          await _vmService?.callServiceExtension(
        'ext.flutter.debugPaint',
      );
      await _vmService?.callServiceExtension(
        'ext.flutter.debugPaint',
        args: <dynamic, dynamic>{
          'enabled': !(response.json['enabled'] == 'true')
        },
      );
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugToggleDebugCheckElevationsEnabled() async {
    try {
      final vmservice.Response response =
          await _vmService?.callServiceExtension(
        'ext.flutter.debugCheckElevationsEnabled',
      );
      await _vmService?.callServiceExtension(
        'ext.flutter.debugCheckElevationsEnabled',
        args: <dynamic, dynamic>{
          'enabled': !(response.json['enabled'] == 'true')
        },
      );
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugTogglePerformanceOverlayOverride() async {
    try {
      final vmservice.Response response = await _vmService
          ?.callServiceExtension('ext.flutter.showPerformanceOverlay');
      await _vmService?.callServiceExtension(
        'ext.flutter.showPerformanceOverlay',
        args: <dynamic, dynamic>{
          'enabled': !(response.json['enabled'] == 'true')
        },
      );
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugToggleWidgetInspector() async {
    try {
      final vmservice.Response response = await _vmService
          ?.callServiceExtension('ext.flutter.debugToggleWidgetInspector');
      await _vmService?.callServiceExtension(
        'ext.flutter.debugToggleWidgetInspector',
        args: <dynamic, dynamic>{
          'enabled': !(response.json['enabled'] == 'true')
        },
      );
    } on vmservice.RPCError {
      return;
    }
  }

  @override
  Future<void> debugToggleProfileWidgetBuilds() async {
    try {
      final vmservice.Response response = await _vmService
          ?.callServiceExtension('ext.flutter.profileWidgetBuilds');
      await _vmService?.callServiceExtension(
        'ext.flutter.profileWidgetBuilds',
        args: <dynamic, dynamic>{
          'enabled': !(response.json['enabled'] == 'true')
        },
      );
    } on vmservice.RPCError {
      return;
    }
  }
}

class _ExperimentalResidentWebRunner extends ResidentWebRunner {
  _ExperimentalResidentWebRunner(
    FlutterDevice device, {
    String target,
    @required FlutterProject flutterProject,
    @required bool ipv6,
    @required DebuggingOptions debuggingOptions,
    bool stayResident = true,
    @required List<String> dartDefines,
  }) : super(
          device,
          flutterProject: flutterProject,
          target: target ?? fs.path.join('lib', 'main.dart'),
          debuggingOptions: debuggingOptions,
          ipv6: ipv6,
          stayResident: stayResident,
          dartDefines: dartDefines,
        );

  @override
  Future<int> run({
    Completer<DebugConnectionInfo> connectionInfoCompleter,
    Completer<void> appStartedCompleter,
    String route,
  }) async {
    firstBuildTime = DateTime.now();
    final ApplicationPackage package = await ApplicationPackageFactory.instance.getPackageForPlatform(
      TargetPlatform.web_javascript,
      applicationBinary: null,
    );
    if (package == null) {
      printError('This application is not configured to build on the web.');
      printError('To add web support to a project, run `flutter create .`.');
      return 1;
    }
    if (!fs.isFileSync(mainPath)) {
      String message = 'Tried to run $mainPath, but that file does not exist.';
      if (target == null) {
        message +=
            '\nConsider using the -t option to specify the Dart file to start.';
      }
      printError(message);
      return 1;
    }
    final String modeName = debuggingOptions.buildInfo.friendlyModeName;
    printStatus('Launching ${getDisplayPath(target)} on ${device.device.name} in $modeName mode...');
    final String effectiveHostname = debuggingOptions.hostname ?? 'localhost';
    final int hostPort = debuggingOptions.port == null
        ? await os.findFreePort()
        : int.tryParse(debuggingOptions.port);
    device.devFS = WebDevFS(
      effectiveHostname,
      hostPort,
      packagesFilePath,
    );
    await device.devFS.create();
    await _updateDevFS(fullRestart: true);
    device.generator.accept();
    await device.device.startApp(
      package,
      mainPath: target,
      debuggingOptions: debuggingOptions,
      platformArgs: <String, Object>{
        'uri': 'http://$effectiveHostname:$hostPort',
      },
    );
    return attach(
      connectionInfoCompleter: connectionInfoCompleter,
      appStartedCompleter: appStartedCompleter,
    );
  }

  @override
  Future<OperationResult> restart({
    bool fullRestart = false,
    bool pause = false,
    String reason,
    bool benchmarkMode = false,
  }) async {
    final Stopwatch timer = Stopwatch()..start();
    final Status status = logger.startProgress(
      'Performing hot restart...',
      timeout: supportsServiceProtocol
          ? timeoutConfiguration.fastOperation
          : timeoutConfiguration.slowOperation,
      progressId: 'hot.restart',
    );

    final UpdateFSReport report = await _updateDevFS(fullRestart: fullRestart);
    if (report.success) {
      device.generator.accept();
    } else {
      await device.generator.reject();
    }
    final String modules = report.invalidatedModules
      .map((String module) => '"$module"')
      .join(',');

    try {
      if (fullRestart) {
        await _wipConnection?.sendCommand('Page.reload');
      } else {
        await _wipConnection?.debugger
            ?.sendCommand('Runtime.evaluate', params: <String, Object>{
          'expression': 'window.\$hotReloadHook([$modules])',
          'awaitPromise': true,
          'returnByValue': true,
        });
      }
    } on WipError catch (err) {
      printError(err.toString());
      return OperationResult(1, err.toString());
    } finally {
      status.stop();
    }
    final String verb = fullRestart ? 'Restarted' : 'Reloaded';
    printStatus('$verb application in ${getElapsedAsMilliseconds(timer.elapsed)}.');
    if (!fullRestart) {
      flutterUsage.sendTiming('hot', 'web-incremental-restart', timer.elapsed);
    }
    HotEvent(
      'restart',
      targetPlatform: getNameForTargetPlatform(TargetPlatform.web_javascript),
      sdkName: await device.device.sdkNameAndVersion,
      emulator: false,
      fullRestart: true,
      reason: reason,
    ).send();
    return OperationResult.ok;
  }

  Future<UpdateFSReport> _updateDevFS({bool fullRestart = false}) async {
    final bool isFirstUpload = !assetBundle.wasBuiltOnce();
    final bool rebuildBundle = assetBundle.needsBuild();
    if (rebuildBundle) {
      printTrace('Updating assets');
      final int result = await assetBundle.build();
      if (result != 0) {
        return UpdateFSReport(success: false);
      }
    }
    final List<Uri> invalidatedFiles =
        await projectFileInvalidator.findInvalidated(
      lastCompiled: device.devFS.lastCompiled,
      urisToMonitor: device.devFS.sources,
      packagesPath: packagesFilePath,
    );
    final Status devFSStatus = logger.startProgress(
      'Syncing files to device ${device.device.name}...',
      timeout: timeoutConfiguration.fastOperation,
    );
    final UpdateFSReport report = await device.devFS.update(
      mainPath: mainPath,
      target: target,
      bundle: assetBundle,
      firstBuildTime: firstBuildTime,
      bundleFirstUpload: isFirstUpload,
      generator: device.generator,
      fullRestart: fullRestart,
      dillOutputPath: dillOutputPath,
      projectRootPath: projectRootPath,
      pathToReload: getReloadPath(fullRestart: fullRestart),
      invalidatedFiles: invalidatedFiles,
      trackWidgetCreation: true,
    );
    devFSStatus.stop();
    printTrace('Synced ${getSizeAsMB(report.syncedBytes)}.');
    return report;
  }

  @override
  Future<int> attach({
    Completer<DebugConnectionInfo> connectionInfoCompleter,
    Completer<void> appStartedCompleter,
  }) async {
    if (device.device is ChromeDevice) {
      final Chrome chrome = await ChromeLauncher.connectedInstance;
      final ChromeTab chromeTab = await chrome.chromeConnection.getTab((ChromeTab chromeTab) {
        return chromeTab.url.contains(debuggingOptions.hostname);
      });
      _wipConnection = await chromeTab.connect();
    }
    appStartedCompleter?.complete();
    connectionInfoCompleter?.complete();
    if (stayResident) {
      await waitForAppToFinish();
    } else {
      await stopEchoingDeviceLog();
      await exitApp();
    }
    await cleanupAtFinish();
    return 0;
  }
}

class _DwdsResidentWebRunner extends ResidentWebRunner {
  _DwdsResidentWebRunner(
    FlutterDevice device, {
    String target,
    @required FlutterProject flutterProject,
    @required bool ipv6,
    @required DebuggingOptions debuggingOptions,
    bool stayResident = true,
    @required List<String> dartDefines,
  }) : super(
          device,
          flutterProject: flutterProject,
          target: target ?? fs.path.join('lib', 'main.dart'),
          debuggingOptions: debuggingOptions,
          ipv6: ipv6,
          stayResident: stayResident,
          dartDefines: dartDefines,
        );

  @override
  Future<int> run({
    Completer<DebugConnectionInfo> connectionInfoCompleter,
    Completer<void> appStartedCompleter,
    String route,
  }) async {
    firstBuildTime = DateTime.now();
    final ApplicationPackage package = await ApplicationPackageFactory.instance.getPackageForPlatform(
      TargetPlatform.web_javascript,
      applicationBinary: null,
    );
    if (package == null) {
      printError('This application is not configured to build on the web.');
      printError('To add web support to a project, run `flutter create .`.');
      return 1;
    }
    if (!fs.isFileSync(mainPath)) {
      String message = 'Tried to run $mainPath, but that file does not exist.';
      if (target == null) {
        message +=
            '\nConsider using the -t option to specify the Dart file to start.';
      }
      printError(message);
      return 1;
    }
    final String modeName = debuggingOptions.buildInfo.friendlyModeName;
    printStatus(
        'Launching ${getDisplayPath(target)} on ${device.device.name} in $modeName mode...');
    Status buildStatus;
    bool statusActive = false;
    try {
      // dwds does not handle uncaught exceptions from its servers. To work
      // around this, we need to catch all uncaught exceptions and determine if
      // they are fatal or not.
      buildStatus = logger.startProgress('Building application for the web...', timeout: null);
      statusActive = true;
      final int result = await asyncGuard(() async {
        _webFs = await webFsFactory(
          target: target,
          flutterProject: flutterProject,
          buildInfo: debuggingOptions.buildInfo,
          initializePlatform: debuggingOptions.initializePlatform,
          hostname: debuggingOptions.hostname,
          port: debuggingOptions.port,
          skipDwds: !_enableDwds,
          dartDefines: dartDefines,
        );
        // When connecting to a browser, update the message with a seemsSlow notification
        // to handle the case where we fail to connect.
        buildStatus.stop();
        statusActive = false;
        if (supportsServiceProtocol) {
          buildStatus = logger.startProgress(
            'Attempting to connect to browser instance..',
            timeout: const Duration(seconds: 30),
          );
          statusActive = true;
        }
        await device.device.startApp(
          package,
          mainPath: target,
          debuggingOptions: debuggingOptions,
          platformArgs: <String, Object>{
            'uri': _webFs.uri,
          },
        );
        if (_enableDwds) {
          final bool useDebugExtension = device.device is WebServerDevice && debuggingOptions.startPaused;
          _connectionResult = await _webFs.connect(useDebugExtension);
          unawaited(_connectionResult.debugConnection.onDone.whenComplete(_cleanupAndExit));
        }
        if (statusActive) {
          buildStatus.stop();
          statusActive = false;
        }
        appStartedCompleter?.complete();
        return attach(
          connectionInfoCompleter: connectionInfoCompleter,
          appStartedCompleter: appStartedCompleter,
        );
      });
      return result;
    } on VersionSkew {
      // Thrown if an older build daemon is already running.
      throwToolExit(
          'Another build daemon is already running with an older version.\n'
          'Try exiting other Flutter processes in this project and try again.');
    } on OptionsSkew {
      // Thrown if a build daemon is already running with different configuration.
      throwToolExit(
          'Another build daemon is already running with different configuration.\n'
          'Exit other Flutter processes running in this project and try again.');
    } on WebSocketException {
      throwToolExit('Failed to connect to WebSocket.');
    } on BuildException {
      throwToolExit('Failed to build application for the Web.');
    } on ChromeDebugException catch (err, stackTrace) {
      throwToolExit(
          'Failed to establish connection with Chrome. Try running the application again.\n'
          'If this problem persists, please file an issue with the details below:\n$err\n$stackTrace');
    } on AppConnectionException {
      throwToolExit(
          'Failed to establish connection with the application instance in Chrome.\n'
          'This can happen if the websocket connection used by the web tooling is '
          'unabled to correctly establish a connection, for example due to a firewall.');
    } on MissingPortFile {
      throwToolExit(
          'Failed to connect to build daemon.\nThe daemon either failed to '
          'start or was killed by another process.');
    } on SocketException catch (err) {
      throwToolExit(err.toString());
    } on StateError catch (err) {
      final String message = err.toString();
      if (message.contains('Unable to start build daemon')) {
        throwToolExit('Failed to start build daemon. The process might have '
            'exited unexpectedly during startup. Try running the application '
            'again.');
      }
      rethrow;
    } finally {
      if (statusActive) {
        buildStatus.stop();
      }
    }
    return 1;
  }

  @override
  Future<OperationResult> restart({
    bool fullRestart = false,
    bool pause = false,
    String reason,
    bool benchmarkMode = false,
  }) async {
    final Stopwatch timer = Stopwatch()..start();
    final Status status = logger.startProgress(
      'Performing hot restart...',
      timeout: supportsServiceProtocol
          ? timeoutConfiguration.fastOperation
          : timeoutConfiguration.slowOperation,
      progressId: 'hot.restart',
    );
    final bool success = await _webFs.recompile();
    if (!success) {
      status.stop();
      return OperationResult(1, 'Failed to recompile application.');
    }
    if (supportsServiceProtocol) {
      // Send an event for only recompilation.
      final Duration recompileDuration = timer.elapsed;
      flutterUsage.sendTiming('hot', 'web-recompile', recompileDuration);
      try {
        final vmservice.Response reloadResponse = fullRestart
          ? await _vmService.callServiceExtension('fullReload')
          : await _vmService.callServiceExtension('hotRestart');
        final String verb = fullRestart ? 'Restarted' : 'Reloaded';
        printStatus(
            '$verb application in ${getElapsedAsMilliseconds(timer.elapsed)}.');

        // Send timing analytics for full restart and for refresh.
        final bool wasSuccessful = reloadResponse.type == 'Success';
        if (!wasSuccessful) {
          return OperationResult(1, reloadResponse.toString());
        }
        if (!fullRestart) {
          flutterUsage.sendTiming('hot', 'web-restart', timer.elapsed);
          flutterUsage.sendTiming('hot', 'web-refresh', timer.elapsed - recompileDuration);
        }
        return OperationResult.ok;
      } on vmservice.RPCError {
        return OperationResult(1, 'Page requires refresh.');
      } finally {
        status.stop();
        HotEvent(
          'restart',
          targetPlatform: getNameForTargetPlatform(TargetPlatform.web_javascript),
          sdkName: await device.device.sdkNameAndVersion,
          emulator: false,
          fullRestart: true,
          reason: reason,
        ).send();
      }
    }
    // Allows browser refresh hot restart on non-debug builds.
    if (device.device is ChromeDevice && !isRunningDebug) {
      try {
        final Chrome chrome = await ChromeLauncher.connectedInstance;
        final ChromeTab chromeTab = await chrome.chromeConnection.getTab((ChromeTab chromeTab) {
          return chromeTab.url.contains(debuggingOptions.hostname);
        });
        final WipConnection wipConnection = await chromeTab.connect();
        await wipConnection.sendCommand('Page.reload');
        status.stop();
        return OperationResult.ok;
      } catch (err) {
        // Ignore error and continue with posted message;
      }
    }
    status.stop();
    printStatus('Recompile complete. Page requires refresh.');
    return OperationResult.ok;
  }

  @override
  Future<int> attach({
    Completer<DebugConnectionInfo> connectionInfoCompleter,
    Completer<void> appStartedCompleter,
  }) async {
    Uri websocketUri;
    if (supportsServiceProtocol) {
      // Cleanup old subscriptions. These will throw if there isn't anything
      // listening, which is fine because that is what we want to ensure.
      try {
        await _vmService.streamCancel('Stdout');
      } on vmservice.RPCError {
        // It is safe to ignore this error because we expect an error to be
        // thrown if we're not already subscribed.
      }
      try {
        await _vmService.streamListen('Stdout');
      } on vmservice.RPCError {
        // It is safe to ignore this error because we expect an error to be
        // thrown if we're not already subscribed.
      }
      _stdOutSub = _vmService.onStdoutEvent.listen((vmservice.Event log) {
        final String message = utf8.decode(base64.decode(log.bytes)).trim();
        printStatus(message);
      });
      unawaited(_vmService.registerService('reloadSources', 'FlutterTools'));
      websocketUri = Uri.parse(_connectionResult.debugConnection.uri);
      // Always run main after connecting because start paused doesn't work yet.
      if (!debuggingOptions.startPaused || !supportsServiceProtocol) {
        _connectionResult.appConnection.runMain();
      } else {
        StreamSubscription<void> resumeSub;
        resumeSub = _connectionResult.debugConnection.vmService.onDebugEvent
            .listen((vmservice.Event event) {
          if (event.type == vmservice.EventKind.kResume) {
            _connectionResult.appConnection.runMain();
            resumeSub.cancel();
          }
        });
      }
    }
    if (websocketUri != null) {
      printStatus('Debug service listening on $websocketUri');
    }
    connectionInfoCompleter?.complete(DebugConnectionInfo(wsUri: websocketUri));

    if (stayResident) {
      await waitForAppToFinish();
    } else {
      await stopEchoingDeviceLog();
      await exitApp();
    }
    await cleanupAtFinish();
    return 0;
  }
}
