// 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:async/async.dart';
import 'package:meta/meta.dart';
import 'package:uuid/uuid.dart';

import '../android/android_workflow.dart';
import '../application_package.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/terminal.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../convert.dart';
import '../daemon.dart';
import '../device.dart';
import '../device_port_forwarder.dart';
import '../emulator.dart';
import '../features.dart';
import '../globals.dart' as globals;
import '../project.dart';
import '../proxied_devices/file_transfer.dart';
import '../resident_runner.dart';
import '../run_cold.dart';
import '../run_hot.dart';
import '../runner/flutter_command.dart';
import '../vmservice.dart';
import '../web/web_runner.dart';

const String protocolVersion = '0.6.1';

/// A server process command. This command will start up a long-lived server.
/// It reads JSON-RPC based commands from stdin, executes them, and returns
/// JSON-RPC based responses and events to stdout.
///
/// It can be shutdown with a `daemon.shutdown` command (or by killing the
/// process).
class DaemonCommand extends FlutterCommand {
  DaemonCommand({ this.hidden = false }) {
    argParser.addOption(
      'listen-on-tcp-port',
      help: 'If specified, the daemon will be listening for commands on the specified port instead of stdio.',
      valueHelp: 'port',
    );
  }

  @override
  final String name = 'daemon';

  @override
  final String description = 'Run a persistent, JSON-RPC based server to communicate with devices.';

  @override
  final String category = FlutterCommandCategory.tools;

  @override
  final bool hidden;

  @override
  Future<FlutterCommandResult> runCommand() async {
    if (argResults!['listen-on-tcp-port'] != null) {
      int? port;
      try {
        port = int.parse(stringArgDeprecated('listen-on-tcp-port')!);
      } on FormatException catch (error) {
        throwToolExit('Invalid port for `--listen-on-tcp-port`: $error');
      }

      await _DaemonServer(
        port: port,
        logger: StdoutLogger(
          terminal: globals.terminal,
          stdio: globals.stdio,
          outputPreferences: globals.outputPreferences,
        ),
        notifyingLogger: asLogger<NotifyingLogger>(globals.logger),
      ).run();
      return FlutterCommandResult.success();
    }
    globals.printStatus('Starting device daemon...');
    final Daemon daemon = Daemon(
      DaemonConnection(
        daemonStreams: DaemonStreams.fromStdio(globals.stdio, logger: globals.logger),
        logger: globals.logger,
      ),
      notifyingLogger: asLogger<NotifyingLogger>(globals.logger),
    );
    final int code = await daemon.onExit;
    if (code != 0) {
      throwToolExit('Daemon exited with non-zero exit code: $code', exitCode: code);
    }
    return FlutterCommandResult.success();
  }
}

class _DaemonServer {
  _DaemonServer({
    this.port,
    this.logger,
    this.notifyingLogger,
  });

  final int? port;

  /// Stdout logger used to print general server-related errors.
  final Logger? logger;

  // Logger that sends the message to the other end of daemon connection.
  final NotifyingLogger? notifyingLogger;

  Future<void> run() async {
    final ServerSocket serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, port!);
    logger!.printStatus('Daemon server listening on ${serverSocket.port}');

    final StreamSubscription<Socket> subscription = serverSocket.listen(
      (Socket socket) async {
        // We have to listen to socket.done. Otherwise when the connection is
        // reset, we will receive an uncatchable exception.
        // https://github.com/dart-lang/sdk/issues/25518
        final Future<void> socketDone = socket.done.catchError((Object error, StackTrace stackTrace) {
          logger!.printError('Socket error: $error');
          logger!.printTrace('$stackTrace');
        });
        final Daemon daemon = Daemon(
          DaemonConnection(
            daemonStreams: DaemonStreams.fromSocket(socket, logger: logger!),
            logger: logger!,
          ),
          notifyingLogger: notifyingLogger,
        );
        await daemon.onExit;
        await socketDone;
      },
    );

    // Wait indefinitely until the server closes.
    await subscription.asFuture<void>();
    await subscription.cancel();
  }
}

typedef CommandHandler = Future<Object?>? Function(Map<String, Object?> args);
typedef CommandHandlerWithBinary = Future<Object?> Function(Map<String, Object?> args, Stream<List<int>>? binary);

class Daemon {
  Daemon(
    this.connection, {
    this.notifyingLogger,
    this.logToStdout = false,
  }) {
    // Set up domains.
    registerDomain(daemonDomain = DaemonDomain(this));
    registerDomain(appDomain = AppDomain(this));
    registerDomain(deviceDomain = DeviceDomain(this));
    registerDomain(emulatorDomain = EmulatorDomain(this));
    registerDomain(devToolsDomain = DevToolsDomain(this));
    registerDomain(proxyDomain = ProxyDomain(this));

    // Start listening.
    _commandSubscription = connection.incomingCommands.listen(
      _handleRequest,
      onDone: () {
        shutdown();
        if (!_onExitCompleter.isCompleted) {
          _onExitCompleter.complete(0);
        }
      },
    );
  }

  final DaemonConnection connection;

  late DaemonDomain daemonDomain;
  late AppDomain appDomain;
  late DeviceDomain deviceDomain;
  EmulatorDomain? emulatorDomain;
  DevToolsDomain? devToolsDomain;
  late ProxyDomain proxyDomain;
  StreamSubscription<DaemonMessage>? _commandSubscription;

  final NotifyingLogger? notifyingLogger;
  final bool logToStdout;

  final Completer<int> _onExitCompleter = Completer<int>();
  final Map<String, Domain> _domainMap = <String, Domain>{};

  @visibleForTesting
  void registerDomain(Domain domain) {
    _domainMap[domain.name] = domain;
  }

  Future<int> get onExit => _onExitCompleter.future;

  void _handleRequest(DaemonMessage request) {
    // {id, method, params}

    // [id] is an opaque type to us.
    final Object? id = request.data['id'];

    if (id == null) {
      globals.stdio.stderrWrite('no id for request: $request\n');
      return;
    }

    try {
      final String method = request.data['method']! as String;
      assert(method != null);
      if (!method.contains('.')) {
        throw DaemonException('method not understood: $method');
      }

      final String prefix = method.substring(0, method.indexOf('.'));
      final String name = method.substring(method.indexOf('.') + 1);
      if (_domainMap[prefix] == null) {
        throw DaemonException('no domain for method: $method');
      }

      _domainMap[prefix]!.handleCommand(name, id, castStringKeyedMap(request.data['params']) ?? const <String, Object?>{}, request.binary);
    } on Exception catch (error, trace) {
      connection.sendErrorResponse(id, _toJsonable(error), trace);
    }
  }

  Future<void> shutdown({ Object? error }) async {
    await devToolsDomain?.dispose();
    await _commandSubscription?.cancel();
    await connection.dispose();
    for (final Domain domain in _domainMap.values) {
      await domain.dispose();
    }
    if (!_onExitCompleter.isCompleted) {
      if (error == null) {
        _onExitCompleter.complete(0);
      } else {
        _onExitCompleter.completeError(error);
      }
    }
  }
}

abstract class Domain {
  Domain(this.daemon, this.name);


  final Daemon daemon;
  final String name;
  final Map<String, CommandHandler> _handlers = <String, CommandHandler>{};
  final Map<String, CommandHandlerWithBinary> _handlersWithBinary = <String, CommandHandlerWithBinary>{};

  void registerHandler(String name, CommandHandler handler) {
    assert(!_handlers.containsKey(name));
    assert(!_handlersWithBinary.containsKey(name));
    _handlers[name] = handler;
  }

  void registerHandlerWithBinary(String name, CommandHandlerWithBinary handler) {
    assert(!_handlers.containsKey(name));
    assert(!_handlersWithBinary.containsKey(name));
    _handlersWithBinary[name] = handler;
  }

  @override
  String toString() => name;

  void handleCommand(String command, Object id, Map<String, Object?> args, Stream<List<int>>? binary) {
    Future<Object?>.sync(() {
      if (_handlers.containsKey(command)) {
        return _handlers[command]!(args);
      } else if (_handlersWithBinary.containsKey(command)) {
        return _handlersWithBinary[command]!(args, binary);
      }
      throw DaemonException('command not understood: $name.$command');
    }).then<Object?>((Object? result) {
      daemon.connection.sendResponse(id, _toJsonable(result));
      return null;
    }).catchError((Object error, StackTrace stackTrace) {
      daemon.connection.sendErrorResponse(id, _toJsonable(error), stackTrace);
      return null;
    });
  }

  void sendEvent(String name, [ Object? args, List<int>? binary ]) {
    daemon.connection.sendEvent(name, _toJsonable(args), binary);
  }

  String? _getStringArg(Map<String, Object?> args, String name, { bool required = false }) {
    if (required && !args.containsKey(name)) {
      throw DaemonException('$name is required');
    }
    final Object? val = args[name];
    if (val != null && val is! String) {
      throw DaemonException('$name is not a String');
    }
    return val as String?;
  }

  bool? _getBoolArg(Map<String, Object?> args, String name, { bool required = false }) {
    if (required && !args.containsKey(name)) {
      throw DaemonException('$name is required');
    }
    final Object? val = args[name];
    if (val != null && val is! bool) {
      throw DaemonException('$name is not a bool');
    }
    return val as bool?;
  }

  int? _getIntArg(Map<String, Object?> args, String name, { bool required = false }) {
    if (required && !args.containsKey(name)) {
      throw DaemonException('$name is required');
    }
    final Object? val = args[name];
    if (val != null && val is! int) {
      throw DaemonException('$name is not an int');
    }
    return val as int?;
  }

  Future<void> dispose() async { }
}

/// This domain responds to methods like [version] and [shutdown].
///
/// This domain fires the `daemon.logMessage` event.
class DaemonDomain extends Domain {
  DaemonDomain(Daemon daemon) : super(daemon, 'daemon') {
    registerHandler('version', version);
    registerHandler('shutdown', shutdown);
    registerHandler('getSupportedPlatforms', getSupportedPlatforms);

    sendEvent(
      'daemon.connected',
      <String, Object?>{
        'version': protocolVersion,
        'pid': pid,
      },
    );

    _subscription = daemon.notifyingLogger!.onMessage.listen((LogMessage message) {
      if (daemon.logToStdout) {
        if (message.level == 'status') {
          // We use `print()` here instead of `stdout.writeln()` in order to
          // capture the print output for testing.
          // ignore: avoid_print
          print(message.message);
        } else if (message.level == 'error' || message.level == 'warning') {
          globals.stdio.stderrWrite('${message.message}\n');
          if (message.stackTrace != null) {
            globals.stdio.stderrWrite(
              '${message.stackTrace.toString().trimRight()}\n',
            );
          }
        }
      } else {
        if (message.stackTrace != null) {
          sendEvent('daemon.logMessage', <String, Object?>{
            'level': message.level,
            'message': message.message,
            'stackTrace': message.stackTrace.toString(),
          });
        } else {
          sendEvent('daemon.logMessage', <String, Object?>{
            'level': message.level,
            'message': message.message,
          });
        }
      }
    });
  }

  StreamSubscription<LogMessage>? _subscription;

  Future<String> version(Map<String, Object?> args) {
    return Future<String>.value(protocolVersion);
  }

  /// Sends a request back to the client asking it to expose/tunnel a URL.
  ///
  /// This method should only be called if the client opted-in with the
  /// --web-allow-expose-url switch. The client may return the same URL back if
  /// tunnelling is not required for a given URL.
  Future<String> exposeUrl(String url) async {
    final Object? res = await daemon.connection.sendRequest('app.exposeUrl', <String, String>{'url': url});
    if (res is Map<String, Object?> && res['url'] is String) {
      return res['url']! as String;
    } else {
      globals.printError('Invalid response to exposeUrl - params should include a String url field');
      return url;
    }
  }

  Future<void> shutdown(Map<String, Object?> args) {
    Timer.run(daemon.shutdown);
    return Future<void>.value();
  }

  @override
  Future<void> dispose() async {
    await _subscription?.cancel();
  }

  /// Enumerates the platforms supported by the provided project.
  ///
  /// This does not filter based on the current workflow restrictions, such
  /// as whether command line tools are installed or whether the host platform
  /// is correct.
  Future<Map<String, Object>> getSupportedPlatforms(Map<String, Object?> args) async {
    final String? projectRoot = _getStringArg(args, 'projectRoot', required: true);
    final List<String> result = <String>[];
    try {
      final FlutterProject flutterProject = FlutterProject.fromDirectory(globals.fs.directory(projectRoot));
      final Set<SupportedPlatform> supportedPlatforms = flutterProject.getSupportedPlatforms().toSet();
      if (featureFlags.isLinuxEnabled && supportedPlatforms.contains(SupportedPlatform.linux)) {
        result.add('linux');
      }
      if (featureFlags.isMacOSEnabled && supportedPlatforms.contains(SupportedPlatform.macos)) {
        result.add('macos');
      }
      if (featureFlags.isWindowsEnabled && supportedPlatforms.contains(SupportedPlatform.windows)) {
        result.add('windows');
      }
      if (featureFlags.isIOSEnabled && supportedPlatforms.contains(SupportedPlatform.ios)) {
        result.add('ios');
      }
      if (featureFlags.isAndroidEnabled && supportedPlatforms.contains(SupportedPlatform.android)) {
        result.add('android');
      }
      if (featureFlags.isWebEnabled && supportedPlatforms.contains(SupportedPlatform.web)) {
        result.add('web');
      }
      if (featureFlags.isFuchsiaEnabled && supportedPlatforms.contains(SupportedPlatform.fuchsia)) {
        result.add('fuchsia');
      }
      if (featureFlags.areCustomDevicesEnabled) {
        result.add('custom');
      }
      return <String, Object>{
        'platforms': result,
      };
    } on Exception catch (err, stackTrace) {
      sendEvent('log', <String, Object?>{
        'log': 'Failed to parse project metadata',
        'stackTrace': stackTrace.toString(),
        'error': true,
      });
      // On any sort of failure, fall back to Android and iOS for backwards
      // comparability.
      return <String, Object>{
        'platforms': <String>[
          'android',
          'ios',
        ],
      };
    }
  }
}

typedef RunOrAttach = Future<void> Function({
  Completer<DebugConnectionInfo>? connectionInfoCompleter,
  Completer<void>? appStartedCompleter,
});

/// This domain responds to methods like [start] and [stop].
///
/// It fires events for application start, stop, and stdout and stderr.
class AppDomain extends Domain {
  AppDomain(Daemon daemon) : super(daemon, 'app') {
    registerHandler('restart', restart);
    registerHandler('callServiceExtension', callServiceExtension);
    registerHandler('stop', stop);
    registerHandler('detach', detach);
  }

  static const Uuid _uuidGenerator = Uuid();

  static String _getNewAppId() => _uuidGenerator.v4();

  final List<AppInstance> _apps = <AppInstance>[];

  final DebounceOperationQueue<OperationResult, OperationType> operationQueue = DebounceOperationQueue<OperationResult, OperationType>();

  Future<AppInstance> startApp(
    Device device,
    String projectDirectory,
    String target,
    String? route,
    DebuggingOptions options,
    bool enableHotReload, {
    File? applicationBinary,
    required bool trackWidgetCreation,
    String? projectRootPath,
    String? packagesFilePath,
    String? dillOutputPath,
    bool ipv6 = false,
    bool multidexEnabled = false,
    String? isolateFilter,
    bool machine = true,
    String? userIdentifier,
  }) async {
    if (!await device.supportsRuntimeMode(options.buildInfo.mode)) {
      throw Exception(
        '${sentenceCase(options.buildInfo.friendlyModeName)} '
        'mode is not supported for ${device.name}.',
      );
    }

    // We change the current working directory for the duration of the `start` command.
    final Directory cwd = globals.fs.currentDirectory;
    globals.fs.currentDirectory = globals.fs.directory(projectDirectory);
    final FlutterProject flutterProject = FlutterProject.current();

    final FlutterDevice flutterDevice = await FlutterDevice.create(
      device,
      target: target,
      buildInfo: options.buildInfo,
      platform: globals.platform,
      userIdentifier: userIdentifier,
    );

    ResidentRunner runner;

    if (await device.targetPlatform == TargetPlatform.web_javascript) {
      runner = webRunnerFactory!.createWebRunner(
        flutterDevice,
        flutterProject: flutterProject,
        target: target,
        debuggingOptions: options,
        ipv6: ipv6,
        stayResident: true,
        urlTunneller: options.webEnableExposeUrl! ? daemon.daemonDomain.exposeUrl : null,
        machine: machine,
        usage: globals.flutterUsage,
        systemClock: globals.systemClock,
        logger: globals.logger,
        fileSystem: globals.fs,
      );
    } else if (enableHotReload) {
      runner = HotRunner(
        <FlutterDevice>[flutterDevice],
        target: target,
        debuggingOptions: options,
        applicationBinary: applicationBinary,
        projectRootPath: projectRootPath,
        dillOutputPath: dillOutputPath,
        ipv6: ipv6,
        multidexEnabled: multidexEnabled,
        hostIsIde: true,
        machine: machine,
      );
    } else {
      runner = ColdRunner(
        <FlutterDevice>[flutterDevice],
        target: target,
        debuggingOptions: options,
        applicationBinary: applicationBinary,
        ipv6: ipv6,
        multidexEnabled: multidexEnabled,
        machine: machine,
      );
    }

    return launch(
      runner,
      ({
        Completer<DebugConnectionInfo>? connectionInfoCompleter,
        Completer<void>? appStartedCompleter,
      }) {
        return runner.run(
          connectionInfoCompleter: connectionInfoCompleter,
          appStartedCompleter: appStartedCompleter,
          enableDevTools: true,
          route: route,
        );
      },
      device,
      projectDirectory,
      enableHotReload,
      cwd,
      LaunchMode.run,
      asLogger<AppRunLogger>(globals.logger),
    );
  }

  Future<AppInstance> launch(
    ResidentRunner runner,
    RunOrAttach runOrAttach,
    Device device,
    String? projectDirectory,
    bool enableHotReload,
    Directory cwd,
    LaunchMode launchMode,
    AppRunLogger logger,
  ) async {
    final AppInstance app = AppInstance(_getNewAppId(),
        runner: runner, logToStdout: daemon.logToStdout, logger: logger);
    _apps.add(app);

    // Set the domain and app for the given AppRunLogger. This allows the logger
    // to log messages containing the app ID to the host.
    logger.domain = this;
    logger.app = app;

    _sendAppEvent(app, 'start', <String, Object?>{
      'deviceId': device.id,
      'directory': projectDirectory,
      'supportsRestart': isRestartSupported(enableHotReload, device),
      'launchMode': launchMode.toString(),
    });

    Completer<DebugConnectionInfo>? connectionInfoCompleter;

    if (runner.debuggingEnabled) {
      connectionInfoCompleter = Completer<DebugConnectionInfo>();
      // We don't want to wait for this future to complete and callbacks won't fail.
      // As it just writes to stdout.
      unawaited(connectionInfoCompleter.future.then<void>(
        (DebugConnectionInfo info) {
          final Map<String, Object?> params = <String, Object?>{
            // The web vmservice proxy does not have an http address.
            'port': info.httpUri?.port ?? info.wsUri!.port,
            'wsUri': info.wsUri.toString(),
          };
          if (info.baseUri != null) {
            params['baseUri'] = info.baseUri;
          }
          _sendAppEvent(app, 'debugPort', params);
        },
      ));
    }
    final Completer<void> appStartedCompleter = Completer<void>();
    // We don't want to wait for this future to complete, and callbacks won't fail,
    // as it just writes to stdout.
    unawaited(appStartedCompleter.future.then<void>((void value) {
      _sendAppEvent(app, 'started');
    }));

    await app._runInZone<void>(this, () async {
      try {
        await runOrAttach(
          connectionInfoCompleter: connectionInfoCompleter,
          appStartedCompleter: appStartedCompleter,
        );
        _sendAppEvent(app, 'stop');
      } on Exception catch (error, trace) {
        _sendAppEvent(app, 'stop', <String, Object?>{
          'error': _toJsonable(error),
          'trace': '$trace',
        });
      } finally {
        // If the full directory is used instead of the path then this causes
        // a TypeError with the ErrorHandlingFileSystem.
        globals.fs.currentDirectory = cwd.path;
        _apps.remove(app);
      }
    });
    return app;
  }

  bool isRestartSupported(bool enableHotReload, Device device) =>
      enableHotReload && device.supportsHotRestart;

  final int _hotReloadDebounceDurationMs = 50;

  Future<OperationResult>? restart(Map<String, Object?> args) async {
    final String? appId = _getStringArg(args, 'appId', required: true);
    final bool fullRestart = _getBoolArg(args, 'fullRestart') ?? false;
    final bool pauseAfterRestart = _getBoolArg(args, 'pause') ?? false;
    final String? restartReason = _getStringArg(args, 'reason');
    final bool debounce = _getBoolArg(args, 'debounce') ?? false;
    // This is an undocumented parameter used for integration tests.
    final int? debounceDurationOverrideMs = _getIntArg(args, 'debounceDurationOverrideMs');

    final AppInstance? app = _getApp(appId);
    if (app == null) {
      throw DaemonException("app '$appId' not found");
    }

    return _queueAndDebounceReloadAction(
      app,
      fullRestart ? OperationType.restart: OperationType.reload,
      debounce,
      debounceDurationOverrideMs,
      () {
        return app.restart(
            fullRestart: fullRestart,
            pause: pauseAfterRestart,
            reason: restartReason);
      },
    )!;
  }

  /// Debounce and queue reload actions.
  ///
  /// Only one reload action will run at a time. Actions requested in quick
  /// succession (within [_hotReloadDebounceDuration]) will be merged together
  /// and all return the same result. If an action is requested after an identical
  /// action has already started, it will be queued and run again once the first
  /// action completes.
  Future<OperationResult>? _queueAndDebounceReloadAction(
    AppInstance app,
    OperationType operationType,
    bool debounce,
    int? debounceDurationOverrideMs,
    Future<OperationResult> Function() action,
  ) {
    final Duration debounceDuration = debounce
        ? Duration(milliseconds: debounceDurationOverrideMs ?? _hotReloadDebounceDurationMs)
        : Duration.zero;

    return operationQueue.queueAndDebounce(
      operationType,
      debounceDuration,
      () => app._runInZone<OperationResult>(this, action),
    );
  }

  /// Returns an error, or the service extension result (a map with two fixed
  /// keys, `type` and `method`). The result may have one or more additional keys,
  /// depending on the specific service extension end-point. For example:
  ///
  ///     {
  ///       "value":"android",
  ///       "type":"_extensionType",
  ///       "method":"ext.flutter.platformOverride"
  ///     }
  Future<Map<String, Object?>> callServiceExtension(Map<String, Object?> args) async {
    final String? appId = _getStringArg(args, 'appId', required: true);
    final String methodName = _getStringArg(args, 'methodName')!;
    final Map<String, Object?>? params = args['params'] == null ? <String, Object?>{} : castStringKeyedMap(args['params']);

    final AppInstance? app = _getApp(appId);
    if (app == null) {
      throw DaemonException("app '$appId' not found");
    }
    final FlutterDevice device = app.runner!.flutterDevices.first;
    final List<FlutterView> views = await device.vmService!.getFlutterViews();
    final Map<String, Object?>? result = await device
      .vmService!
      .invokeFlutterExtensionRpcRaw(
        methodName,
        args: params,
        isolateId: views
          .first.uiIsolate!.id!
      );
    if (result == null) {
      throw DaemonException('method not available: $methodName');
    }

    if (result.containsKey('error')) {
      // ignore: only_throw_errors
      throw result['error']!;
    }

    return result;
  }

  Future<bool> stop(Map<String, Object?> args) async {
    final String? appId = _getStringArg(args, 'appId', required: true);

    final AppInstance? app = _getApp(appId);
    if (app == null) {
      throw DaemonException("app '$appId' not found");
    }

    return app.stop().then<bool>(
      (void value) => true,
      onError: (Object? error, StackTrace stack) {
        _sendAppEvent(app, 'log', <String, Object?>{'log': '$error', 'error': true});
        app.closeLogger();
        _apps.remove(app);
        return false;
      },
    );
  }

  Future<bool> detach(Map<String, Object?> args) async {
    final String? appId = _getStringArg(args, 'appId', required: true);

    final AppInstance? app = _getApp(appId);
    if (app == null) {
      throw DaemonException("app '$appId' not found");
    }

    return app.detach().then<bool>(
      (void value) => true,
      onError: (Object? error, StackTrace stack) {
        _sendAppEvent(app, 'log', <String, Object?>{'log': '$error', 'error': true});
        app.closeLogger();
        _apps.remove(app);
        return false;
      },
    );
  }

  AppInstance? _getApp(String? id) {
    for (final AppInstance app in _apps) {
      if (app.id == id) {
        return app;
      }
    }
    return null;
  }

  void _sendAppEvent(AppInstance app, String name, [ Map<String, Object?>? args ]) {
    sendEvent('app.$name', <String, Object?>{
      'appId': app.id,
      ...?args,
    });
  }
}

typedef _DeviceEventHandler = void Function(Device device);

/// This domain lets callers list and monitor connected devices.
///
/// It exports a `getDevices()` call, as well as firing `device.added` and
/// `device.removed` events.
class DeviceDomain extends Domain {
  DeviceDomain(Daemon daemon) : super(daemon, 'device') {
    registerHandler('getDevices', getDevices);
    registerHandler('discoverDevices', discoverDevices);
    registerHandler('enable', enable);
    registerHandler('disable', disable);
    registerHandler('forward', forward);
    registerHandler('unforward', unforward);
    registerHandler('supportsRuntimeMode', supportsRuntimeMode);
    registerHandler('uploadApplicationPackage', uploadApplicationPackage);
    registerHandler('logReader.start', startLogReader);
    registerHandler('logReader.stop', stopLogReader);
    registerHandler('startApp', startApp);
    registerHandler('stopApp', stopApp);
    registerHandler('takeScreenshot', takeScreenshot);

    // Use the device manager discovery so that client provided device types
    // are usable via the daemon protocol.
    globals.deviceManager!.deviceDiscoverers.forEach(addDeviceDiscoverer);
  }

  /// An incrementing number used to generate unique ids.
  int _id = 0;
  final Map<String, ApplicationPackage?> _applicationPackages = <String, ApplicationPackage?>{};
  final Map<String, DeviceLogReader> _logReaders = <String, DeviceLogReader>{};

  void addDeviceDiscoverer(DeviceDiscovery discoverer) {
    if (!discoverer.supportsPlatform) {
      return;
    }

    if (discoverer is PollingDeviceDiscovery) {
      _discoverers.add(discoverer);
      discoverer.onAdded.listen(_onDeviceEvent('device.added'));
      discoverer.onRemoved.listen(_onDeviceEvent('device.removed'));
    }
  }

  Future<void> _serializeDeviceEvents = Future<void>.value();

  _DeviceEventHandler _onDeviceEvent(String eventName) {
    return (Device device) {
      _serializeDeviceEvents = _serializeDeviceEvents.then<void>((_) async {
        try {
          final Map<String, Object?> response = await _deviceToMap(device);
          sendEvent(eventName, response);
        } on Exception catch (err) {
          globals.printError('$err');
        }
      });
    };
  }

  final List<PollingDeviceDiscovery> _discoverers = <PollingDeviceDiscovery>[];

  /// Return a list of the current devices, with each device represented as a map
  /// of properties (id, name, platform, ...).
  Future<List<Map<String, Object?>>> getDevices([ Map<String, Object?>? args ]) async {
    return <Map<String, Object?>>[
      for (final PollingDeviceDiscovery discoverer in _discoverers)
        for (final Device device in await discoverer.devices)
          await _deviceToMap(device),
    ];
  }

  /// Return a list of the current devices, discarding existing cache of devices.
  Future<List<Map<String, Object?>>> discoverDevices([ Map<String, Object?>? args ]) async {
    return <Map<String, Object?>>[
      for (final PollingDeviceDiscovery discoverer in _discoverers)
        for (final Device device in await discoverer.discoverDevices())
          await _deviceToMap(device),
    ];
  }

  /// Enable device events.
  Future<void> enable(Map<String, Object?> args) async {
    for (final PollingDeviceDiscovery discoverer in _discoverers) {
      discoverer.startPolling();
    }
  }

  /// Disable device events.
  Future<void> disable(Map<String, Object?> args) async {
    for (final PollingDeviceDiscovery discoverer in _discoverers) {
      discoverer.stopPolling();
    }
  }

  /// Forward a host port to a device port.
  Future<Map<String, Object?>> forward(Map<String, Object?> args) async {
    final String? deviceId = _getStringArg(args, 'deviceId', required: true);
    final int devicePort = _getIntArg(args, 'devicePort', required: true)!;
    int? hostPort = _getIntArg(args, 'hostPort');

    final Device? device = await daemon.deviceDomain._getDevice(deviceId);
    if (device == null) {
      throw DaemonException("device '$deviceId' not found");
    }

    hostPort = await device.portForwarder!.forward(devicePort, hostPort: hostPort);

    return <String, Object?>{'hostPort': hostPort};
  }

  /// Removes a forwarded port.
  Future<void> unforward(Map<String, Object?> args) async {
    final String? deviceId = _getStringArg(args, 'deviceId', required: true);
    final int devicePort = _getIntArg(args, 'devicePort', required: true)!;
    final int hostPort = _getIntArg(args, 'hostPort', required: true)!;

    final Device? device = await daemon.deviceDomain._getDevice(deviceId);
    if (device == null) {
      throw DaemonException("device '$deviceId' not found");
    }

    return device.portForwarder!.unforward(ForwardedPort(hostPort, devicePort));
  }

  /// Returns whether a device supports runtime mode.
  Future<bool> supportsRuntimeMode(Map<String, Object?> args) async {
    final String? deviceId = _getStringArg(args, 'deviceId', required: true);
    final Device? device = await daemon.deviceDomain._getDevice(deviceId);
    if (device == null) {
      throw DaemonException("device '$deviceId' not found");
    }
    final String buildMode = _getStringArg(args, 'buildMode', required: true)!;
    return await device.supportsRuntimeMode(getBuildModeForName(buildMode));
  }

  /// Creates an application package from a file in the temp directory.
  Future<String> uploadApplicationPackage(Map<String, Object?> args) async {
    final TargetPlatform targetPlatform = getTargetPlatformForName(_getStringArg(args, 'targetPlatform', required: true)!);
    final File applicationBinary = daemon.proxyDomain.tempDirectory.childFile(_getStringArg(args, 'applicationBinary', required: true)!);
    final ApplicationPackage? applicationPackage = await ApplicationPackageFactory.instance!.getPackageForPlatform(
      targetPlatform,
      applicationBinary: applicationBinary,
    );
    final String id = 'application_package_${_id++}';
    _applicationPackages[id] = applicationPackage;
    return id;
  }

  /// Starts the log reader on the device.
  Future<String> startLogReader(Map<String, Object?> args) async {
    final String? deviceId = _getStringArg(args, 'deviceId', required: true);
    final Device? device = await daemon.deviceDomain._getDevice(deviceId);
    if (device == null) {
      throw DaemonException("device '$deviceId' not found");
    }
    final String? applicationPackageId = _getStringArg(args, 'applicationPackageId');
    final ApplicationPackage? applicationPackage = applicationPackageId != null ? _applicationPackages[applicationPackageId] : null;
    final String id = '${deviceId}_${_id++}';

    final DeviceLogReader logReader = await device.getLogReader(app: applicationPackage);
    logReader.logLines.listen((String log) => sendEvent('device.logReader.logLines.$id', log));

    _logReaders[id] = logReader;

    return id;
  }

  /// Stops a log reader that was previously started.
  Future<void> stopLogReader(Map<String, Object?> args) async {
    final String? id = _getStringArg(args, 'id', required: true);
    _logReaders.remove(id)?.dispose();
  }

  /// Starts an app on a device.
  Future<Map<String, Object?>> startApp(Map<String, Object?> args) async {
    final String? deviceId = _getStringArg(args, 'deviceId', required: true);
    final Device? device = await daemon.deviceDomain._getDevice(deviceId);
    if (device == null) {
      throw DaemonException("device '$deviceId' not found");
    }
    final String? applicationPackageId = _getStringArg(args, 'applicationPackageId', required: true);
    final ApplicationPackage applicationPackage = _applicationPackages[applicationPackageId!]!;

    final LaunchResult result = await device.startApp(
      applicationPackage,
      debuggingOptions: DebuggingOptions.fromJson(
        castStringKeyedMap(args['debuggingOptions'])!,
        // We are using prebuilts, build info does not matter here.
        BuildInfo.debug,
      ),
      mainPath: _getStringArg(args, 'mainPath'),
      route: _getStringArg(args, 'route'),
      platformArgs: castStringKeyedMap(args['platformArgs']) ?? const <String, Object>{},
      prebuiltApplication: _getBoolArg(args, 'prebuiltApplication') ?? false,
      ipv6: _getBoolArg(args, 'ipv6') ?? false,
      userIdentifier: _getStringArg(args, 'userIdentifier'),
    );
    return <String, Object?>{
      'started': result.started,
      'observatoryUri': result.observatoryUri?.toString(),
    };
  }

  /// Stops an app.
  Future<bool> stopApp(Map<String, Object?> args) async {
    final String? deviceId = _getStringArg(args, 'deviceId', required: true);
    final Device? device = await daemon.deviceDomain._getDevice(deviceId);
    if (device == null) {
      throw DaemonException("device '$deviceId' not found");
    }
    final String? applicationPackageId = _getStringArg(args, 'applicationPackageId', required: true);
    final ApplicationPackage applicationPackage = _applicationPackages[applicationPackageId!]!;
    return device.stopApp(
      applicationPackage,
      userIdentifier: _getStringArg(args, 'userIdentifier'),
    );
  }

  /// Takes a screenshot.
  Future<String?> takeScreenshot(Map<String, Object?> args) async {
    final String? deviceId = _getStringArg(args, 'deviceId', required: true);
    final Device? device = await daemon.deviceDomain._getDevice(deviceId);
    if (device == null) {
      throw DaemonException("device '$deviceId' not found");
    }
    final String tempFileName = 'screenshot_${_id++}';
    final File tempFile = daemon.proxyDomain.tempDirectory.childFile(tempFileName);
    await device.takeScreenshot(tempFile);
    if (await tempFile.exists()) {
      final String imageBase64 = base64.encode(await tempFile.readAsBytes());
      return imageBase64;
    } else {
      return null;
    }
  }

  @override
  Future<void> dispose() {
    for (final PollingDeviceDiscovery discoverer in _discoverers) {
      discoverer.dispose();
    }
    return Future<void>.value();
  }

  /// Return the device matching the deviceId field in the args.
  Future<Device?> _getDevice(String? deviceId) async {
    for (final PollingDeviceDiscovery discoverer in _discoverers) {
      final List<Device> devices = await discoverer.devices;
      Device? device;
      for (final Device localDevice in devices) {
        if (localDevice.id == deviceId) {
          device = localDevice;
        }
      }
      if (device != null) {
        return device;
      }
    }
    return null;
  }
}

class DevToolsDomain extends Domain {
  DevToolsDomain(Daemon daemon) : super(daemon, 'devtools') {
    registerHandler('serve', serve);
  }

  DevtoolsLauncher? _devtoolsLauncher;

  Future<Map<String, Object?>> serve([ Map<String, Object?>? args ]) async {
    _devtoolsLauncher ??= DevtoolsLauncher.instance;
    final DevToolsServerAddress? server = await _devtoolsLauncher?.serve();
    return<String, Object?>{
      'host': server?.host,
      'port': server?.port,
    };
  }

  @override
  Future<void> dispose() async {
    await _devtoolsLauncher?.close();
  }
}

Future<Map<String, Object?>> _deviceToMap(Device device) async {
  return <String, Object?>{
    'id': device.id,
    'name': device.name,
    'platform': getNameForTargetPlatform(await device.targetPlatform),
    'emulator': await device.isLocalEmulator,
    'category': device.category?.toString(),
    'platformType': device.platformType?.toString(),
    'ephemeral': device.ephemeral,
    'emulatorId': await device.emulatorId,
    'sdk': await device.sdkNameAndVersion,
    'capabilities': <String, Object>{
      'hotReload': device.supportsHotReload,
      'hotRestart': device.supportsHotRestart,
      'screenshot': device.supportsScreenshot,
      'fastStart': device.supportsFastStart,
      'flutterExit': device.supportsFlutterExit,
      'hardwareRendering': await device.supportsHardwareRendering,
      'startPaused': device.supportsStartPaused,
    },
  };
}

Map<String, Object?> _emulatorToMap(Emulator emulator) {
  return <String, Object?>{
    'id': emulator.id,
    'name': emulator.name,
    'category': emulator.category.toString(),
    'platformType': emulator.platformType.toString(),
  };
}

Map<String, Object?> _operationResultToMap(OperationResult result) {
  return <String, Object?>{
    'code': result.code,
    'message': result.message,
  };
}

Object? _toJsonable(Object? obj) {
  if (obj is String || obj is int || obj is bool || obj is Map<Object?, Object?> || obj is List<Object?> || obj == null) {
    return obj;
  }
  if (obj is OperationResult) {
    return _operationResultToMap(obj);
  }
  if (obj is ToolExit) {
    return obj.message;
  }
  return '$obj';
}

class NotifyingLogger extends DelegatingLogger {
  NotifyingLogger({ required this.verbose, required Logger parent }) : super(parent) {
    _messageController = StreamController<LogMessage>.broadcast(
      onListen: _onListen,
    );
  }

  final bool verbose;
  final List<LogMessage> messageBuffer = <LogMessage>[];
  late StreamController<LogMessage> _messageController;

  void _onListen() {
    if (messageBuffer.isNotEmpty) {
      messageBuffer.forEach(_messageController.add);
      messageBuffer.clear();
    }
  }

  Stream<LogMessage> get onMessage => _messageController.stream;

  @override
  void printError(
    String message, {
    StackTrace? stackTrace,
    bool? emphasis = false,
    TerminalColor? color,
    int? indent,
    int? hangingIndent,
    bool? wrap,
  }) {
    _sendMessage(LogMessage('error', message, stackTrace));
  }

  @override
  void printWarning(
    String message, {
    bool? emphasis = false,
    TerminalColor? color,
    int? indent,
    int? hangingIndent,
    bool? wrap,
  }) {
    _sendMessage(LogMessage('warning', message));
  }

  @override
  void printStatus(
    String message, {
    bool? emphasis = false,
    TerminalColor? color,
    bool? newline = true,
    int? indent,
    int? hangingIndent,
    bool? wrap,
  }) {
    _sendMessage(LogMessage('status', message));
  }

  @override
  void printBox(String message, {
    String? title,
  }) {
    _sendMessage(LogMessage('status', title == null ? message : '$title: $message'));
  }

  @override
  void printTrace(String message) {
    if (!verbose) {
      return;
    }
    super.printError(message);
  }

  @override
  Status startProgress(
    String message, {
    Duration? timeout,
    String? progressId,
    bool multilineOutput = false,
    bool includeTiming = true,
    int progressIndicatorPadding = kDefaultStatusPadding,
  }) {
    assert(timeout != null);
    printStatus(message);
    return SilentStatus(
      stopwatch: Stopwatch(),
    );
  }

  void _sendMessage(LogMessage logMessage) {
    if (_messageController.hasListener) {
      return _messageController.add(logMessage);
    }
    messageBuffer.add(logMessage);
  }

  void dispose() {
    _messageController.close();
  }

  @override
  void sendEvent(String name, [Map<String, Object?>? args]) { }

  @override
  bool get supportsColor => false;

  @override
  bool get hasTerminal => false;

  // This method is only relevant for terminals.
  @override
  void clear() { }
}

/// A running application, started by this daemon.
class AppInstance {
  AppInstance(this.id, { this.runner, this.logToStdout = false, required AppRunLogger logger })
    : _logger = logger;

  final String id;
  final ResidentRunner? runner;
  final bool logToStdout;
  final AppRunLogger _logger;

  Future<OperationResult> restart({ bool fullRestart = false, bool pause = false, String? reason }) {
    return runner!.restart(fullRestart: fullRestart, pause: pause, reason: reason);
  }

  Future<void> stop() => runner!.exit();
  Future<void> detach() => runner!.detach();

  void closeLogger() {
    _logger.close();
  }

  Future<T> _runInZone<T>(AppDomain domain, FutureOr<T> Function() method) async {
    return method();
  }
}

/// This domain responds to methods like [getEmulators] and [launch].
class EmulatorDomain extends Domain {
  EmulatorDomain(Daemon daemon) : super(daemon, 'emulator') {
    registerHandler('getEmulators', getEmulators);
    registerHandler('launch', launch);
    registerHandler('create', create);
  }

  EmulatorManager emulators = EmulatorManager(
    fileSystem: globals.fs,
    logger: globals.logger,
    androidSdk: globals.androidSdk,
    processManager: globals.processManager,
    androidWorkflow: androidWorkflow!,
  );

  Future<List<Map<String, Object?>>> getEmulators([ Map<String, Object?>? args ]) async {
    final List<Emulator> list = await emulators.getAllAvailableEmulators();
    return list.map<Map<String, Object?>>(_emulatorToMap).toList();
  }

  Future<void> launch(Map<String, Object?> args) async {
    final String emulatorId = _getStringArg(args, 'emulatorId', required: true)!;
    final bool coldBoot = _getBoolArg(args, 'coldBoot') ?? false;
    final List<Emulator> matches =
        await emulators.getEmulatorsMatching(emulatorId);
    if (matches.isEmpty) {
      throw DaemonException("emulator '$emulatorId' not found");
    } else if (matches.length > 1) {
      throw DaemonException("multiple emulators match '$emulatorId'");
    } else {
      await matches.first.launch(coldBoot: coldBoot);
    }
  }

  Future<Map<String, Object?>> create(Map<String, Object?> args) async {
    final String? name = _getStringArg(args, 'name');
    final CreateEmulatorResult res = await emulators.createEmulator(name: name);
    return <String, Object?>{
      'success': res.success,
      'emulatorName': res.emulatorName,
      'error': res.error,
    };
  }
}

class ProxyDomain extends Domain {
  ProxyDomain(Daemon daemon) : super(daemon, 'proxy') {
    registerHandlerWithBinary('writeTempFile', writeTempFile);
    registerHandler('calculateFileHashes', calculateFileHashes);
    registerHandlerWithBinary('updateFile', updateFile);
    registerHandler('connect', connect);
    registerHandler('disconnect', disconnect);
    registerHandlerWithBinary('write', write);
  }

  final Map<String, Socket> _forwardedConnections = <String, Socket>{};
  int _id = 0;

  /// Writes to a file in a local temporary directory.
  Future<void> writeTempFile(Map<String, Object?> args, Stream<List<int>>? binary) async {
    final String path = _getStringArg(args, 'path', required: true)!;
    final File file = tempDirectory.childFile(path);
    await file.parent.create(recursive: true);
    await file.openWrite().addStream(binary!);
  }

  /// Calculate rolling hashes for a file in the local temporary directory.
  Future<Map<String, Object?>?> calculateFileHashes(Map<String, Object?> args) async {
    final String path = _getStringArg(args, 'path', required: true)!;
    final File file = tempDirectory.childFile(path);
    if (!await file.exists()) {
      return null;
    }
    final BlockHashes result = await FileTransfer().calculateBlockHashesOfFile(file);
    return result.toJson();
  }

  Future<bool?> updateFile(Map<String, Object?> args, Stream<List<int>>? binary) async {
    final String path = _getStringArg(args, 'path', required: true)!;
    final File file = tempDirectory.childFile(path);
    if (!await file.exists()) {
      return null;
    }
    final List<Map<String, Object?>> deltaJson = (args['delta']! as List<Object?>).cast<Map<String, Object?>>();
    final List<FileDeltaBlock> delta = FileDeltaBlock.fromJsonList(deltaJson);
    final bool result = await FileTransfer().rebuildFile(file, delta, binary!);
    return result;
  }

  /// Opens a connection to a local port, and returns the connection id.
  Future<String> connect(Map<String, Object?> args) async {
    final int targetPort = _getIntArg(args, 'port', required: true)!;
    final String id = 'portForwarder_${targetPort}_${_id++}';

    Socket? socket;

    try {
      socket = await Socket.connect(InternetAddress.loopbackIPv4, targetPort);
    } on SocketException {
      globals.logger.printTrace('Connecting to localhost:$targetPort failed with IPv4');
    }

    try {
      // If connecting to IPv4 loopback interface fails, try IPv6.
      socket ??= await Socket.connect(InternetAddress.loopbackIPv6, targetPort);
    } on SocketException {
      globals.logger.printError('Connecting to localhost:$targetPort failed');
    }

    if (socket == null) {
      throw Exception('Failed to connect to the port');
    }

    _forwardedConnections[id] = socket;
    socket.listen((List<int> data) {
      sendEvent('proxy.data.$id', null, data);
    }, onError: (Object error, StackTrace stackTrace) {
      // Socket error, probably disconnected.
      globals.logger.printTrace('Socket error: $error, $stackTrace');
    });

    unawaited(socket.done.catchError((Object error, StackTrace stackTrace) {
      // Socket error, probably disconnected.
      globals.logger.printTrace('Socket error: $error, $stackTrace');
    }).then((Object? _) {
      sendEvent('proxy.disconnected.$id');
    }));
    return id;
  }

  /// Disconnects from a previously established connection.
  Future<bool> disconnect(Map<String, Object?> args) async {
    final String? id = _getStringArg(args, 'id', required: true);
    if (_forwardedConnections.containsKey(id)) {
      await _forwardedConnections.remove(id)?.close();
      return true;
    }
    return false;
  }

  /// Writes to a previously established connection.
  Future<bool> write(Map<String, Object?> args, Stream<List<int>>? binary) async {
    final String? id = _getStringArg(args, 'id', required: true);
    if (_forwardedConnections.containsKey(id)) {
      final StreamSubscription<List<int>> subscription = binary!.listen(_forwardedConnections[id!]!.add);
      await subscription.asFuture<void>();
      await subscription.cancel();
      return true;
    }
    return false;
  }

  @override
  Future<void> dispose() async {
    for (final Socket connection in _forwardedConnections.values) {
      connection.destroy();
    }
    // We deliberately not clean up the tempDirectory here. The application package files that
    // are transferred into this directory through ProxiedDevices are left in the directory
    // to be reused on any subsequent runs.
  }

  Directory? _tempDirectory;
  Directory get tempDirectory => _tempDirectory ??= globals.fs.systemTempDirectory.childDirectory('flutter_tool_daemon')..createSync();
}

/// A [Logger] which sends log messages to a listening daemon client.
///
/// This class can either:
///   1) Send stdout messages and progress events to the client IDE
///   1) Log messages to stdout and send progress events to the client IDE
//
// TODO(devoncarew): To simplify this code a bit, we could choose to specialize
// this class into two, one for each of the above use cases.
class AppRunLogger extends DelegatingLogger {
  AppRunLogger({ required Logger parent }) : super(parent);

  AppDomain? domain;
  late AppInstance app;
  int _nextProgressId = 0;

  Status? _status;

  @override
  Status startProgress(
    String message, {
    Duration? timeout,
    String? progressId,
    bool multilineOutput = false,
    bool includeTiming = true,
    int progressIndicatorPadding = kDefaultStatusPadding,
  }) {
    final int id = _nextProgressId++;

    _sendProgressEvent(
      eventId: id.toString(),
      eventType: progressId,
      message: message,
    );

    _status = SilentStatus(
      onFinish: () {
        _status = null;
        _sendProgressEvent(
          eventId: id.toString(),
          eventType: progressId,
          finished: true,
        );
      }, stopwatch: Stopwatch())..start();
    return _status!;
  }

  void close() {
    domain = null;
  }

  void _sendProgressEvent({
    required String eventId,
    required String? eventType,
    bool finished = false,
    String? message,
  }) {
    if (domain == null) {
      // If we're sending progress events before an app has started, send the
      // progress messages as plain status messages.
      if (message != null) {
        printStatus(message);
      }
    } else {
      final Map<String, Object?> event = <String, Object?>{
        'id': eventId,
        'progressId': eventType,
        if (message != null) 'message': message,
        if (finished != null) 'finished': finished,
      };

      domain!._sendAppEvent(app, 'progress', event);
    }
  }

  @override
  void sendEvent(String name, [Map<String, Object?>? args, List<int>? binary]) {
    if (domain == null) {
      printStatus('event sent after app closed: $name');
    } else {
      domain!.sendEvent(name, args, binary);
    }
  }

  @override
  bool get supportsColor => false;

  @override
  bool get hasTerminal => false;

  // This method is only relevant for terminals.
  @override
  void clear() { }
}

class LogMessage {
  LogMessage(this.level, this.message, [this.stackTrace]);

  final String level;
  final String message;
  final StackTrace? stackTrace;
}

/// The method by which the Flutter app was launched.
class LaunchMode {
  const LaunchMode._(this._value);

  /// The app was launched via `flutter run`.
  static const LaunchMode run = LaunchMode._('run');

  /// The app was launched via `flutter attach`.
  static const LaunchMode attach = LaunchMode._('attach');

  final String _value;

  @override
  String toString() => _value;
}

enum OperationType {
  reload,
  restart
}

/// A queue that debounces operations for a period and merges operations of the same type.
/// Only one action (or any type) will run at a time. Actions of the same type requested
/// in quick succession will be merged together and all return the same result. If an action
/// is requested after an identical action has already started, it will be queued
/// and run again once the first action completes.
class DebounceOperationQueue<T, K> {
  final Map<K, RestartableTimer> _debounceTimers = <K, RestartableTimer>{};
  final Map<K, Future<T>> _operationQueue = <K, Future<T>>{};
  Future<void>? _inProgressAction;

  Future<T> queueAndDebounce(
    K operationType,
    Duration debounceDuration,
    Future<T> Function() action,
  ) {
    // If there is already an operation of this type waiting to run, reset its
    // debounce timer and return its future.
    if (_operationQueue[operationType] != null) {
      _debounceTimers[operationType]?.reset();
      return _operationQueue[operationType]!;
    }

    // Otherwise, put one in the queue with a timer.
    final Completer<T> completer = Completer<T>();
    _operationQueue[operationType] = completer.future;
    _debounceTimers[operationType] = RestartableTimer(
      debounceDuration,
      () async {
        // Remove us from the queue so we can't be reset now we've started.
        unawaited(_operationQueue.remove(operationType));
        _debounceTimers.remove(operationType);

        // No operations should be allowed to run concurrently even if they're
        // different types.
        while (_inProgressAction != null) {
          await _inProgressAction;
        }

        _inProgressAction = action()
            .then(completer.complete, onError: completer.completeError)
            .whenComplete(() => _inProgressAction = null);
      },
    );

    return completer.future;
  }
}

/// Specialized exception for returning errors to the daemon client.
class DaemonException implements Exception {
  DaemonException(this.message);

  final String message;

  @override
  String toString() => message;
}
