// 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/net.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,
    @required UrlTunneller urlTunneller,
  }) {
    if (featureFlags.isWebIncrementalCompilerEnabled && debuggingOptions.buildInfo.isDebug) {
      return _ExperimentalResidentWebRunner(
        device,
        target: target,
        flutterProject: flutterProject,
        debuggingOptions: debuggingOptions,
        ipv6: ipv6,
        stayResident: stayResident,
        dartDefines: dartDefines,
        // TODO(dantup): If this becomes default it may need to urlTunneller.
      );
    }
    return _DwdsResidentWebRunner(
      device,
      target: target,
      flutterProject: flutterProject,
      debuggingOptions: debuggingOptions,
      ipv6: ipv6,
      stayResident: stayResident,
      dartDefines: dartDefines,
      urlTunneller: urlTunneller,
    );
  }
}

/// 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,
    @required this.urlTunneller,
    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,
        );

  UrlTunneller urlTunneller;

  @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,
          urlTunneller: urlTunneller,
          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;
  }
}
