// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:meta/meta.dart';

import 'application_package.dart';
import 'base/context.dart';
import 'base/dds.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'devfs.dart';
import 'device_port_forwarder.dart';
import 'device_vm_service_discovery_for_attach.dart';
import 'project.dart';
import 'vmservice.dart';
import 'web/compile.dart';
import 'web/devfs_config.dart';

DeviceManager? get deviceManager => context.get<DeviceManager>();

/// A description of the kind of workflow the device supports.
enum Category {
  web._('web'),
  desktop._('desktop'),
  mobile._('mobile');

  const Category._(this.value);

  final String value;

  @override
  String toString() => value;

  static Category? fromString(String category) {
    return const <String, Category>{'web': web, 'desktop': desktop, 'mobile': mobile}[category];
  }
}

/// The platform sub-folder that a device type supports.
enum PlatformType {
  web,
  android,
  ios,
  linux,
  macos,
  windows,
  fuchsia,
  custom;

  @override
  String toString() => name;

  static PlatformType? fromString(String platformType) => values.asNameMap()[platformType];
}

/// A discovery mechanism for flutter-supported development devices.
abstract class DeviceManager {
  DeviceManager({required Logger logger}) : _logger = logger;

  final Logger _logger;

  /// Constructing DeviceManagers is cheap; they only do expensive work if some
  /// of their methods are called.
  List<DeviceDiscovery> get deviceDiscoverers;

  String? _specifiedDeviceId;

  /// A user-specified device ID.
  String? get specifiedDeviceId {
    if (_specifiedDeviceId == null || _specifiedDeviceId == 'all') {
      return null;
    }
    return _specifiedDeviceId;
  }

  set specifiedDeviceId(String? id) {
    _specifiedDeviceId = id;
  }

  /// A minimum duration to use when discovering wireless iOS devices.
  static const minimumWirelessDeviceDiscoveryTimeout = Duration(seconds: 5);

  /// True when the user has specified a single specific device.
  bool get hasSpecifiedDeviceId => specifiedDeviceId != null;

  /// True when the user has specified all devices by setting
  /// specifiedDeviceId = 'all'.
  bool get hasSpecifiedAllDevices => _specifiedDeviceId == 'all';

  /// Get devices filtered by [filter] that match the given device id/name.
  ///
  /// If [filter] is not provided, a default filter that requires devices to be
  /// connected will be used.
  ///
  /// If an exact match is found, return it immediately. Otherwise wait for all
  /// discoverers to complete and return any partial matches.
  Future<List<Device>> getDevicesById(String deviceId, {DeviceDiscoveryFilter? filter}) async {
    filter ??= DeviceDiscoveryFilter();

    final String lowerDeviceId = deviceId.toLowerCase();
    bool exactlyMatchesDeviceId(Device device) =>
        device.id.toLowerCase() == lowerDeviceId || device.name.toLowerCase() == lowerDeviceId;
    bool startsWithDeviceId(Device device) =>
        device.id.toLowerCase().startsWith(lowerDeviceId) ||
        device.name.toLowerCase().startsWith(lowerDeviceId);

    // Some discoverers have hard-coded device IDs and return quickly, and others
    // shell out to other processes and can take longer.
    // If an ID was specified, first check if it was a "well-known" device id.
    final Set<String> wellKnownIds = _platformDiscoverers
        .expand((DeviceDiscovery discovery) => discovery.wellKnownIds)
        .toSet();
    final bool hasWellKnownId = hasSpecifiedDeviceId && wellKnownIds.contains(specifiedDeviceId);

    // Process discoverers as they can return results, so if an exact match is
    // found quickly, we don't wait for all the discoverers to complete.
    final prefixMatches = <Device>[];
    final exactMatchCompleter = Completer<Device>();
    final futureDevices = <Future<List<Device>?>>[
      for (final DeviceDiscovery discoverer in _platformDiscoverers)
        if (!hasWellKnownId || discoverer.wellKnownIds.contains(specifiedDeviceId))
          discoverer
              .devices(filter: filter)
              .then(
                (List<Device> devices) {
                  for (final device in devices) {
                    if (exactlyMatchesDeviceId(device)) {
                      exactMatchCompleter.complete(device);
                      return null;
                    }
                    if (startsWithDeviceId(device)) {
                      prefixMatches.add(device);
                    }
                  }
                  return null;
                },
                onError: (dynamic error, StackTrace stackTrace) {
                  // Return matches from other discoverers even if one fails.
                  _logger.printTrace('Ignored error discovering $deviceId: $error');
                },
              ),
    ];

    // Wait for an exact match, or for all discoverers to return results.
    await Future.any<Object>(<Future<Object>>[
      exactMatchCompleter.future,
      Future.wait<List<Device>?>(futureDevices),
    ]);

    if (exactMatchCompleter.isCompleted) {
      return <Device>[await exactMatchCompleter.future];
    }
    return prefixMatches;
  }

  /// Returns a list of devices filtered by the user-specified device
  /// id/name (if applicable) and [filter].
  ///
  /// If [filter] is not provided, a default filter that requires devices to be
  /// connected will be used.
  Future<List<Device>> getDevices({DeviceDiscoveryFilter? filter}) {
    filter ??= DeviceDiscoveryFilter();
    final String? id = specifiedDeviceId;
    if (id == null) {
      return getAllDevices(filter: filter);
    }
    return getDevicesById(id, filter: filter);
  }

  Iterable<DeviceDiscovery> get _platformDiscoverers {
    return deviceDiscoverers.where((DeviceDiscovery discoverer) => discoverer.supportsPlatform);
  }

  /// Returns a list of devices filtered by [filter].
  ///
  /// If [filter] is not provided, a default filter that requires devices to be
  /// connected will be used.
  Future<List<Device>> getAllDevices({DeviceDiscoveryFilter? filter}) async {
    filter ??= DeviceDiscoveryFilter();
    final List<List<Device>> devices = await Future.wait<List<Device>>(<Future<List<Device>>>[
      for (final DeviceDiscovery discoverer in _platformDiscoverers)
        discoverer.devices(filter: filter),
    ]);

    return devices.expand<Device>((List<Device> deviceList) => deviceList).toList();
  }

  /// Returns a list of devices filtered by [filter]. Discards existing cache of devices.
  ///
  /// If [filter] is not provided, a default filter that requires devices to be
  /// connected will be used.
  ///
  /// Search for devices to populate the cache for no longer than [timeout].
  Future<List<Device>> refreshAllDevices({Duration? timeout, DeviceDiscoveryFilter? filter}) async {
    filter ??= DeviceDiscoveryFilter();
    final List<List<Device>> devices = await Future.wait<List<Device>>(<Future<List<Device>>>[
      for (final DeviceDiscovery discoverer in _platformDiscoverers)
        discoverer.discoverDevices(filter: filter, timeout: timeout),
    ]);

    return devices.expand<Device>((List<Device> deviceList) => deviceList).toList();
  }

  /// Discard existing cache of discoverers that are known to take longer to
  /// discover wireless devices.
  ///
  /// Then, search for devices for those discoverers to populate the cache for
  /// no longer than [timeout].
  Future<void> refreshExtendedWirelessDeviceDiscoverers({
    Duration? timeout,
    DeviceDiscoveryFilter? filter,
  }) async {
    await Future.wait<List<Device>>(<Future<List<Device>>>[
      for (final DeviceDiscovery discoverer in _platformDiscoverers)
        if (discoverer.requiresExtendedWirelessDeviceDiscovery)
          discoverer.discoverDevices(timeout: timeout, forWirelessDiscovery: true),
    ]);
  }

  /// Stop any running extended wireless device discoverers.
  void stopExtendedWirelessDeviceDiscoverers() {
    for (final PollingDeviceDiscovery deviceDiscoverer
        in _platformDiscoverers.whereType<PollingDeviceDiscovery>()) {
      if (deviceDiscoverer.requiresExtendedWirelessDeviceDiscovery) {
        deviceDiscoverer.cancelWirelessDiscovery();
      }
    }
  }

  /// Whether we're capable of listing any devices given the current environment configuration.
  bool get canListAnything {
    return _platformDiscoverers.any((DeviceDiscovery discoverer) => discoverer.canListAnything);
  }

  /// Get diagnostics about issues with any connected devices.
  Future<List<String>> getDeviceDiagnostics() async {
    return <String>[
      for (final DeviceDiscovery discoverer in _platformDiscoverers)
        ...await discoverer.getDiagnostics(),
    ];
  }

  /// Determines how to filter devices.
  ///
  /// By default, filters to only include devices that are supported by Flutter.
  ///
  /// If the user has not specified a device, filters to only include devices
  /// that are supported by Flutter and supported by the project.
  ///
  /// If the user has specified `--device all`, filters to only include devices
  /// that are supported by Flutter, supported by the project, and supported for `all`.
  ///
  /// If [includeDevicesUnsupportedByProject] is true, all devices will be
  /// considered supported by the project, regardless of user specifications.
  ///
  /// This also exists to allow the check to be overridden for google3 clients.
  DeviceDiscoverySupportFilter deviceSupportFilter({
    bool includeDevicesUnsupportedByProject = false,
  }) {
    FlutterProject? flutterProject;
    if (!includeDevicesUnsupportedByProject) {
      flutterProject = FlutterProject.current();
    }
    if (hasSpecifiedAllDevices) {
      return DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutterOrProjectOrAll(
        flutterProject: flutterProject,
      );
    } else if (!hasSpecifiedDeviceId) {
      return DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutterOrProject(
        flutterProject: flutterProject,
      );
    } else {
      return DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutter();
    }
  }

  /// If the user did not specify to run all or a specific device, then attempt
  /// to prioritize ephemeral devices.
  ///
  /// If there is not exactly one ephemeral device return null.
  ///
  /// For example, if the user only typed 'flutter run' and both an Android
  /// device and desktop device are available, choose the Android device.
  ///
  /// Note: ephemeral is nullable for device types where this is not well
  /// defined.
  Device? getSingleEphemeralDevice(List<Device> devices) {
    if (!hasSpecifiedDeviceId) {
      try {
        return devices.singleWhere((Device device) => device.ephemeral);
      } on StateError {
        return null;
      }
    }
    return null;
  }
}

/// A class for determining how to filter devices based on if they are supported.
class DeviceDiscoverySupportFilter {
  /// Filter devices to only include those supported by Flutter.
  DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutter()
    : _excludeDevicesNotSupportedByProject = false,
      _excludeDevicesNotSupportedByAll = false,
      _flutterProject = null;

  /// Filter devices to only include those supported by Flutter and the
  /// provided [flutterProject].
  ///
  /// If [flutterProject] is null, all devices will be considered supported by
  /// the project.
  DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutterOrProject({
    required FlutterProject? flutterProject,
  }) : _flutterProject = flutterProject,
       _excludeDevicesNotSupportedByProject = true,
       _excludeDevicesNotSupportedByAll = false;

  /// Filter devices to only include those supported by Flutter, the provided
  /// [flutterProject], and `--device all`.
  ///
  /// If [flutterProject] is null, all devices will be considered supported by
  /// the project.
  DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutterOrProjectOrAll({
    required FlutterProject? flutterProject,
  }) : _flutterProject = flutterProject,
       _excludeDevicesNotSupportedByProject = true,
       _excludeDevicesNotSupportedByAll = true;

  final FlutterProject? _flutterProject;
  final bool _excludeDevicesNotSupportedByProject;
  final bool _excludeDevicesNotSupportedByAll;

  Future<bool> matchesRequirements(Device device) async {
    final bool meetsSupportByFlutterRequirement = await device.isSupported();
    final bool meetsSupportForProjectRequirement =
        !_excludeDevicesNotSupportedByProject || await isDeviceSupportedForProject(device);
    final bool meetsSupportForAllRequirement =
        !_excludeDevicesNotSupportedByAll || await isDeviceSupportedForAll(device);

    return meetsSupportByFlutterRequirement &&
        meetsSupportForProjectRequirement &&
        meetsSupportForAllRequirement;
  }

  /// User has specified `--device all`.
  ///
  /// Always remove web and fuchsia devices from `all`. This setting
  /// currently requires devices to share a frontend_server and resident
  /// runner instance. Both web and fuchsia require differently configured
  /// compilers, and web requires an entirely different resident runner.
  Future<bool> isDeviceSupportedForAll(Device device) async {
    final TargetPlatform devicePlatform = await device.targetPlatform;
    return await device.isSupported() &&
        devicePlatform != TargetPlatform.fuchsia_arm64 &&
        devicePlatform != TargetPlatform.fuchsia_x64 &&
        devicePlatform != TargetPlatform.web_javascript &&
        await isDeviceSupportedForProject(device);
  }

  /// Returns whether the device is supported for the project.
  ///
  /// A device can be supported by Flutter but not supported for the project
  /// (e.g. when the user has removed the iOS directory from their project).
  ///
  /// This also exists to allow the check to be overridden for google3 clients. If
  /// [_flutterProject] is null then return true.
  Future<bool> isDeviceSupportedForProject(Device device) async {
    if (!await device.isSupported()) {
      return false;
    }
    if (_flutterProject == null) {
      return true;
    }
    return device.isSupportedForProject(_flutterProject);
  }
}

/// A class for filtering devices.
///
/// If [excludeDisconnected] is true, only devices detected as connected will be included.
///
/// If [supportFilter] is provided, only devices matching the requirements will be included.
///
/// If [deviceConnectionInterface] is provided, only devices matching the DeviceConnectionInterface will be included.
class DeviceDiscoveryFilter {
  DeviceDiscoveryFilter({
    this.excludeDisconnected = true,
    this.supportFilter,
    this.deviceConnectionInterface,
  });

  final bool excludeDisconnected;
  final DeviceDiscoverySupportFilter? supportFilter;
  final DeviceConnectionInterface? deviceConnectionInterface;

  Future<bool> matchesRequirements(Device device) async {
    final DeviceDiscoverySupportFilter? localSupportFilter = supportFilter;

    final bool meetsConnectionRequirement = !excludeDisconnected || device.isConnected;
    final bool meetsSupportRequirements =
        localSupportFilter == null || (await localSupportFilter.matchesRequirements(device));
    final bool meetsConnectionInterfaceRequirement = matchesDeviceConnectionInterface(
      device,
      deviceConnectionInterface,
    );

    return meetsConnectionRequirement &&
        meetsSupportRequirements &&
        meetsConnectionInterfaceRequirement;
  }

  Future<List<Device>> filterDevices(List<Device> devices) async {
    devices = <Device>[
      for (final Device device in devices)
        if (await matchesRequirements(device)) device,
    ];
    return devices;
  }

  bool matchesDeviceConnectionInterface(
    Device device,
    DeviceConnectionInterface? deviceConnectionInterface,
  ) {
    if (deviceConnectionInterface == null) {
      return true;
    }
    return device.connectionInterface == deviceConnectionInterface;
  }
}

/// An abstract class to discover and enumerate a specific type of devices.
abstract class DeviceDiscovery {
  bool get supportsPlatform;

  /// Whether this device discovery is capable of listing any devices given the
  /// current environment configuration.
  bool get canListAnything;

  /// Whether this device discovery is known to take longer to discover
  /// wireless devices.
  bool get requiresExtendedWirelessDeviceDiscovery => false;

  /// Return all connected devices, cached on subsequent calls.
  Future<List<Device>> devices({DeviceDiscoveryFilter? filter});

  /// Return all connected devices. Discards existing cache of devices.
  Future<List<Device>> discoverDevices({
    Duration? timeout,
    DeviceDiscoveryFilter? filter,
    bool forWirelessDiscovery = false,
  });

  /// Gets a list of diagnostic messages pertaining to issues with any connected
  /// devices (will be an empty list if there are no issues).
  Future<List<String>> getDiagnostics() => Future<List<String>>.value(<String>[]);

  /// Hard-coded device IDs that the discoverer can produce.
  ///
  /// These values are used by the device discovery to determine if it can
  /// short-circuit the other detectors if a specific ID is provided. If a
  /// discoverer has no valid fixed IDs, these should be left empty.
  ///
  /// For example, 'windows' or 'linux'.
  List<String> get wellKnownIds;
}

/// A [DeviceDiscovery] implementation that uses polling to discover device adds
/// and removals.
abstract class PollingDeviceDiscovery extends DeviceDiscovery {
  PollingDeviceDiscovery(this.name);

  static const _pollingInterval = Duration(seconds: 4);
  static const _pollingTimeout = Duration(seconds: 30);

  final String name;

  @protected
  @visibleForTesting
  final deviceNotifier = ItemListNotifier<Device>();

  Timer? _timer;

  Future<List<Device>> pollingGetDevices({Duration? timeout, bool forWirelessDiscovery = false});

  void startPolling() {
    // Make initial population the default, fast polling timeout.
    _timer ??= _initTimer(null, initialCall: true);
  }

  Timer _initTimer(Duration? pollingTimeout, {bool initialCall = false}) {
    // Poll for devices immediately on the initial call for faster initial population.
    return Timer(initialCall ? Duration.zero : _pollingInterval, () async {
      try {
        final List<Device> devices = await pollingGetDevices(timeout: pollingTimeout);
        deviceNotifier.updateWithNewList(devices);
      } on TimeoutException {
        // Do nothing on a timeout.
      }
      // Subsequent timeouts after initial population should wait longer.
      _timer = _initTimer(_pollingTimeout);
    });
  }

  void stopPolling() {
    _timer?.cancel();
    _timer = null;
  }

  /// Cancels any in-progress, long-running wireless discovery processes.
  Future<void> cancelWirelessDiscovery() async {}

  /// Get devices from cache filtered by [filter].
  ///
  /// If the cache is empty, populate the cache.
  ///
  /// If [filter] is null, it may return devices that are not connected.
  @override
  Future<List<Device>> devices({DeviceDiscoveryFilter? filter}) {
    return _populateDevices(filter: filter);
  }

  /// Empty the cache and repopulate it before getting devices from cache filtered by [filter].
  ///
  /// Search for devices to populate the cache for no longer than [timeout].
  ///
  /// If [filter] is null, it may return devices that are not connected.
  @override
  Future<List<Device>> discoverDevices({
    Duration? timeout,
    DeviceDiscoveryFilter? filter,
    bool forWirelessDiscovery = false,
  }) {
    return _populateDevices(
      timeout: timeout,
      filter: filter,
      resetCache: true,
      forWirelessDiscovery: forWirelessDiscovery,
    );
  }

  /// Get devices from cache filtered by [filter].
  ///
  /// If the cache is empty or [resetCache] is true, populate the cache.
  ///
  /// Search for devices to populate the cache for no longer than [timeout].
  Future<List<Device>> _populateDevices({
    Duration? timeout,
    DeviceDiscoveryFilter? filter,
    bool resetCache = false,
    bool forWirelessDiscovery = false,
  }) async {
    if (!deviceNotifier.isPopulated || resetCache) {
      final List<Device> devices = await pollingGetDevices(
        timeout: timeout,
        forWirelessDiscovery: forWirelessDiscovery,
      );
      // If the cache was populated while the polling was ongoing, do not
      // overwrite the cache unless it's explicitly refreshing the cache.
      if (!deviceNotifier.isPopulated || resetCache) {
        deviceNotifier.updateWithNewList(devices);
      }
    }

    // If a filter is provided, filter cache to only return devices matching.
    if (filter != null) {
      return filter.filterDevices(deviceNotifier.items);
    }
    return deviceNotifier.items;
  }

  Stream<Device> get onAdded {
    return deviceNotifier.onAdded;
  }

  Stream<Device> get onRemoved {
    return deviceNotifier.onRemoved;
  }

  void dispose() => stopPolling();

  @override
  String toString() => '$name device discovery';
}

/// How a device is connected.
enum DeviceConnectionInterface { attached, wireless }

/// Returns the `DeviceConnectionInterface` enum based on its string name.
DeviceConnectionInterface getDeviceConnectionInterfaceForName(String name) {
  return switch (name) {
    'attached' => DeviceConnectionInterface.attached,
    'wireless' => DeviceConnectionInterface.wireless,
    _ => throw Exception('Unsupported DeviceConnectionInterface name "$name"'),
  };
}

/// Returns a `DeviceConnectionInterface`'s string name.
String getNameForDeviceConnectionInterface(DeviceConnectionInterface connectionInterface) {
  return switch (connectionInterface) {
    DeviceConnectionInterface.attached => 'attached',
    DeviceConnectionInterface.wireless => 'wireless',
  };
}

/// A device is a physical hardware that can run a Flutter application.
///
/// This may correspond to a connected iOS or Android device, or represent
/// the host operating system in the case of Flutter Desktop.
abstract class Device {
  Device(
    this.id, {
    required Logger logger,
    required this.category,
    required this.platformType,
    required this.ephemeral,
  }) : dds = DartDevelopmentService(logger: logger);

  final String id;

  /// The [Category] for this device type.
  final Category? category;

  /// The [PlatformType] for this device.
  final PlatformType? platformType;

  /// Whether this is an ephemeral device.
  final bool ephemeral;

  bool get isConnected => true;

  DeviceConnectionInterface get connectionInterface => DeviceConnectionInterface.attached;

  bool get isWirelesslyConnected => connectionInterface == DeviceConnectionInterface.wireless;

  String get name;

  String get displayName {
    String result = name;
    if (isWirelesslyConnected) {
      result += ' (wireless)';
    }
    return result;
  }

  bool get supportsStartPaused => true;

  /// Whether it is an emulated device running on localhost.
  ///
  /// This may return `true` for certain physical Android devices, and is
  /// generally only a best effort guess.
  Future<bool> get isLocalEmulator;

  /// The unique identifier for the emulator that corresponds to this device, or
  /// null if it is not an emulator.
  ///
  /// The ID returned matches that in the output of `flutter emulators`. Fetching
  /// this name may require connecting to the device and if an error occurs null
  /// will be returned.
  Future<String?> get emulatorId;

  /// Whether this device can run the provided [buildMode].
  ///
  /// For example, some emulator architectures cannot run profile or
  /// release builds.
  FutureOr<bool> supportsRuntimeMode(BuildMode buildMode) => true;

  /// Whether the device is a simulator on a platform which supports hardware rendering.
  // This is soft-deprecated since the logic is not correct expect for iOS simulators.
  Future<bool> get supportsHardwareRendering async {
    return true;
  }

  /// Whether the device is supported for the current project directory.
  bool isSupportedForProject(FlutterProject flutterProject);

  /// Check if a version of the given app is already installed.
  ///
  /// Specify [userIdentifier] to check if installed for a particular user (Android only).
  Future<bool> isAppInstalled(ApplicationPackage app, {String? userIdentifier});

  /// Check if the latest build of the [app] is already installed.
  Future<bool> isLatestBuildInstalled(ApplicationPackage app);

  /// Install an app package on the current device.
  ///
  /// Specify [userIdentifier] to install for a particular user (Android only).
  Future<bool> installApp(ApplicationPackage app, {String? userIdentifier});

  /// Uninstall an app package from the current device.
  ///
  /// Specify [userIdentifier] to uninstall for a particular user,
  /// defaults to all users (Android only).
  Future<bool> uninstallApp(ApplicationPackage app, {String? userIdentifier});

  /// Check if the device is supported by Flutter.
  Future<bool> isSupported();

  // String meant to be displayed to the user indicating if the device is
  // supported by Flutter, and, if not, why.
  Future<String> supportMessage() async => await isSupported() ? 'Supported' : 'Unsupported';

  /// The device's platform.
  Future<TargetPlatform> get targetPlatform;

  /// Platform name for display only.
  Future<String> get targetPlatformDisplayName async => (await targetPlatform).getName();

  Future<String> get sdkNameAndVersion;

  /// Create a platform-specific [DevFSWriter] for the given [app], or
  /// null if the device does not support them.
  ///
  /// For example, the desktop device classes can use a writer which
  /// copies the files across the local file system.
  DevFSWriter? createDevFSWriter(ApplicationPackage? app, String? userIdentifier) {
    return null;
  }

  /// Get a log reader for this device.
  ///
  /// If `app` is specified, this will return a log reader specific to that
  /// application. Otherwise, a global log reader will be returned.
  ///
  /// If `includePastLogs` is true and the device type supports it, the log
  /// reader will also include log messages from before the invocation time.
  /// Defaults to false.
  FutureOr<DeviceLogReader> getLogReader({ApplicationPackage? app, bool includePastLogs = false});

  /// Get the port forwarder for this device.
  DevicePortForwarder? get portForwarder;

  /// Get the DDS instance for this device.
  final DartDevelopmentService dds;

  /// Get the DevTools URI for the application instance.
  Uri? get devToolsUri => dds.devToolsUri;

  /// Clear the device's logs.
  void clearLogs();

  /// Get the [VMServiceDiscoveryForAttach] instance for this device, which
  /// discovers, and forwards any necessary ports to the vm service uri of a
  /// running app on the device.
  ///
  /// If `appId` is specified, on supported platforms, the service discovery
  /// will only return the VM service URI from the given app.
  ///
  /// If `fuchsiaModule` is specified, this will only return the VM service uri
  /// from the specified Fuchsia module.
  ///
  /// If `filterDevicePort` is specified, this will only return the VM service
  /// uri that matches the given port on the device.
  VMServiceDiscoveryForAttach getVMServiceDiscoveryForAttach({
    String? appId,
    String? fuchsiaModule,
    int? filterDevicePort,
    int? expectedHostPort,
    required bool ipv6,
    required Logger logger,
  }) => LogScanningVMServiceDiscoveryForAttach(
    Future<DeviceLogReader>.value(getLogReader()),
    portForwarder: portForwarder,
    devicePort: filterDevicePort,
    hostPort: expectedHostPort,
    ipv6: ipv6,
    logger: logger,
  );

  /// Start an app package on the current device.
  ///
  /// [platformArgs] allows callers to pass platform-specific arguments to the
  /// start call. The build mode is not used by all platforms.
  Future<LaunchResult> startApp(
    covariant ApplicationPackage? package, {
    String? mainPath,
    String? route,
    required DebuggingOptions debuggingOptions,
    Map<String, Object?> platformArgs,
    bool prebuiltApplication = false,
    String? userIdentifier,
  });

  /// Whether this device implements support for hot reload.
  bool get supportsHotReload => true;

  /// Whether this device implements support for hot restart.
  bool get supportsHotRestart => true;

  /// Whether Flutter applications running on this device can be terminated
  /// from the VM Service.
  bool get supportsFlutterExit => true;

  /// Whether the device supports taking screenshots of a running flutter
  /// application.
  bool get supportsScreenshot => false;

  /// Whether the Flavors feature ('--flavor') is supported for this device.
  bool get supportsFlavors => false;

  /// Stop an app package on the current device.
  ///
  /// Specify [userIdentifier] to stop app installed to a profile (Android only).
  Future<bool> stopApp(ApplicationPackage? app, {String? userIdentifier});

  /// Query the current application memory usage..
  ///
  /// If the device does not support this callback, an empty map
  /// is returned.
  Future<MemoryInfo> queryMemoryInfo() {
    return Future<MemoryInfo>.value(const MemoryInfo.empty());
  }

  Future<void> takeScreenshot(File outputFile) => Future<void>.error('unimplemented');

  @nonVirtual
  @override
  // ignore: avoid_equals_and_hash_code_on_mutable_classes
  int get hashCode => id.hashCode;

  @nonVirtual
  @override
  // ignore: avoid_equals_and_hash_code_on_mutable_classes
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    return other is Device && other.id == id;
  }

  @override
  String toString() => name;

  static Future<List<String>> descriptions(List<Device> devices) async {
    if (devices.isEmpty) {
      return const <String>[];
    }

    // Extract device information
    final table = <List<String>>[];
    for (final device in devices) {
      var supportIndicator = await device.isSupported() ? '' : ' (unsupported)';
      final TargetPlatform targetPlatform = await device.targetPlatform;
      if (await device.isLocalEmulator) {
        final type = targetPlatform == TargetPlatform.ios ? 'simulator' : 'emulator';
        supportIndicator += ' ($type)';
      }
      table.add(<String>[
        '${device.displayName} (${device.category})',
        device.id,
        await device.targetPlatformDisplayName,
        '${await device.sdkNameAndVersion}$supportIndicator',
      ]);
    }

    // Join columns into lines of text
    return formatTable(table);
  }

  static Future<void> printDevices(
    List<Device> devices,
    Logger logger, {
    String prefix = '',
  }) async {
    for (final String line in await descriptions(devices)) {
      logger.printStatus('$prefix$line');
    }
  }

  static List<String> devicesPlatformTypes(List<Device> devices) {
    return devices.map((Device d) => d.platformType.toString()).toSet().toList()..sort();
  }

  /// Convert the Device object to a JSON representation suitable for serialization.
  Future<Map<String, Object>> toJson() async {
    final bool isLocalEmu = await isLocalEmulator;
    return <String, Object>{
      'name': name,
      'id': id,
      'isSupported': await isSupported(),
      'targetPlatform': (await targetPlatform).getName(),
      'emulator': isLocalEmu,
      'sdk': await sdkNameAndVersion,
      'capabilities': <String, Object>{
        'hotReload': supportsHotReload,
        'hotRestart': supportsHotRestart,
        'screenshot': supportsScreenshot,
        'flutterExit': supportsFlutterExit,
        'hardwareRendering': isLocalEmu && await supportsHardwareRendering,
        'startPaused': supportsStartPaused,
      },
    };
  }

  /// Clean up resources allocated by device.
  ///
  /// For example log readers or port forwarders.
  Future<void> dispose();
}

/// Information about an application's memory usage.
abstract class MemoryInfo {
  /// Const constructor to allow subclasses to be const.
  const MemoryInfo();

  /// Create a [MemoryInfo] object with no information.
  const factory MemoryInfo.empty() = _NoMemoryInfo;

  /// Convert the object to a JSON representation suitable for serialization.
  Map<String, Object> toJson();
}

class _NoMemoryInfo implements MemoryInfo {
  const _NoMemoryInfo();

  @override
  Map<String, Object> toJson() => <String, Object>{};
}

enum ImpellerStatus {
  platformDefault._(null),
  enabled._(true),
  disabled._(false);

  const ImpellerStatus._(this.asBool);

  factory ImpellerStatus.fromBool(bool? b) => switch (b) {
    true => enabled,
    false => disabled,
    null => platformDefault,
  };

  final bool? asBool;
}

class DebuggingOptions {
  DebuggingOptions.enabled(
    this.buildInfo, {
    this.startPaused = false,
    this.disableServiceAuthCodes = false,
    this.enableDds = true,
    this.cacheStartupProfile = false,
    this.dartEntrypointArgs = const <String>[],
    this.dartFlags = '',
    this.enableSoftwareRendering = false,
    this.skiaDeterministicRendering = false,
    this.traceSkia = false,
    this.traceAllowlist,
    this.traceSkiaAllowlist,
    this.traceSystrace = false,
    this.traceToFile,
    this.endlessTraceBuffer = false,
    this.profileMicrotasks = false,
    this.purgePersistentCache = false,
    this.useTestFonts = false,
    this.verboseSystemLogs = false,
    this.hostVmServicePort,
    this.disablePortPublication = false,
    this.deviceVmServicePort,
    this.ddsPort,
    this.devToolsServerAddress,
    this.webEnableExposeUrl,
    this.webUseSseForDebugProxy = true,
    this.webUseSseForDebugBackend = true,
    this.webUseSseForInjectedClient = true,
    this.webRunHeadless = false,
    this.webBrowserDebugPort,
    this.webBrowserFlags = const <String>[],
    this.webEnableExpressionEvaluation = false,
    this.webLaunchUrl,
    bool? webCrossOriginIsolation,
    WebRendererMode? webRenderer,
    this.webUseWasm = false,
    this.vmserviceOutFile,
    this.nativeNullAssertions = false,
    this.enableImpeller = ImpellerStatus.platformDefault,
    this.enableFlutterGpu = false,
    this.enableVulkanValidation = false,
    this.uninstallFirst = false,
    this.uninstallApp = true,
    this.enableDartProfiling = true,
    this.enableHcpp = false,
    this.profileStartup = false,
    this.enableEmbedderApi = false,
    this.usingCISystem = false,
    this.debugLogsDirectoryPath,
    this.enableDevTools = true,
    this.ipv6 = false,
    this.google3WorkspaceRoot,
    this.printDtd = false,
    this.webDevServerConfig,
    this.testFlag = false,
  }) : debuggingEnabled = true,
       webCrossOriginIsolation = webCrossOriginIsolation ?? webUseWasm,
       webRenderer = webRenderer ?? WebRendererMode.getDefault(useWasm: webUseWasm);

  DebuggingOptions.disabled(
    this.buildInfo, {
    this.dartEntrypointArgs = const <String>[],
    this.webEnableExposeUrl,
    this.webUseSseForDebugProxy = true,
    this.webUseSseForDebugBackend = true,
    this.webUseSseForInjectedClient = true,
    this.webRunHeadless = false,
    this.webBrowserDebugPort,
    this.webBrowserFlags = const <String>[],
    this.webLaunchUrl,
    bool? webCrossOriginIsolation,
    WebRendererMode? webRenderer,
    this.webUseWasm = false,
    this.traceAllowlist,
    this.enableImpeller = ImpellerStatus.platformDefault,
    this.enableFlutterGpu = false,
    this.enableVulkanValidation = false,
    this.uninstallFirst = false,
    this.uninstallApp = true,
    this.enableDartProfiling = true,
    this.enableHcpp = false,
    this.profileStartup = false,
    this.enableEmbedderApi = false,
    this.usingCISystem = false,
    this.debugLogsDirectoryPath,
    this.webDevServerConfig,
    this.testFlag = false,
  }) : debuggingEnabled = false,
       useTestFonts = false,
       startPaused = false,
       dartFlags = '',
       disableServiceAuthCodes = false,
       enableDds = false,
       cacheStartupProfile = false,
       enableSoftwareRendering = false,
       skiaDeterministicRendering = false,
       traceSkia = false,
       traceSkiaAllowlist = null,
       traceSystrace = false,
       traceToFile = null,
       endlessTraceBuffer = false,
       profileMicrotasks = false,
       purgePersistentCache = false,
       verboseSystemLogs = false,
       hostVmServicePort = null,
       disablePortPublication = false,
       deviceVmServicePort = null,
       ddsPort = null,
       devToolsServerAddress = null,
       vmserviceOutFile = null,
       webEnableExpressionEvaluation = false,
       webCrossOriginIsolation = webCrossOriginIsolation ?? webUseWasm,
       nativeNullAssertions = false,
       enableDevTools = false,
       ipv6 = false,
       google3WorkspaceRoot = null,
       printDtd = false,
       webRenderer = webRenderer ?? WebRendererMode.getDefault(useWasm: webUseWasm);

  DebuggingOptions._({
    required this.buildInfo,
    required this.debuggingEnabled,
    required this.startPaused,
    required this.dartFlags,
    required this.dartEntrypointArgs,
    required this.disableServiceAuthCodes,
    required this.enableDds,
    required this.cacheStartupProfile,
    required this.enableSoftwareRendering,
    required this.skiaDeterministicRendering,
    required this.traceSkia,
    required this.traceAllowlist,
    required this.traceSkiaAllowlist,
    required this.traceSystrace,
    required this.traceToFile,
    required this.endlessTraceBuffer,
    required this.profileMicrotasks,
    required this.purgePersistentCache,
    required this.useTestFonts,
    required this.verboseSystemLogs,
    required this.hostVmServicePort,
    required this.deviceVmServicePort,
    required this.disablePortPublication,
    required this.ddsPort,
    required this.devToolsServerAddress,
    required this.webEnableExposeUrl,
    required this.webUseSseForDebugProxy,
    required this.webUseSseForDebugBackend,
    required this.webUseSseForInjectedClient,
    required this.webRunHeadless,
    required this.webBrowserDebugPort,
    required this.webBrowserFlags,
    required this.webEnableExpressionEvaluation,
    required this.webLaunchUrl,
    required this.webCrossOriginIsolation,
    required this.webRenderer,
    required this.webUseWasm,
    required this.vmserviceOutFile,
    required this.nativeNullAssertions,
    required this.enableImpeller,
    required this.enableFlutterGpu,
    required this.enableVulkanValidation,
    required this.uninstallFirst,
    required this.uninstallApp,
    required this.enableDartProfiling,
    required this.enableHcpp,
    required this.profileStartup,
    required this.enableEmbedderApi,
    required this.usingCISystem,
    required this.debugLogsDirectoryPath,
    required this.enableDevTools,
    required this.ipv6,
    required this.google3WorkspaceRoot,
    required this.printDtd,
    this.webDevServerConfig,
  }) : testFlag = false;

  final bool debuggingEnabled;

  final BuildInfo buildInfo;
  final bool startPaused;
  final String dartFlags;
  final List<String> dartEntrypointArgs;
  final bool disableServiceAuthCodes;
  final bool enableDds;
  final bool cacheStartupProfile;
  final bool enableSoftwareRendering;
  final bool skiaDeterministicRendering;
  final bool traceSkia;
  final String? traceAllowlist;
  final String? traceSkiaAllowlist;
  final bool traceSystrace;
  final String? traceToFile;
  final bool endlessTraceBuffer;
  final bool profileMicrotasks;
  final bool purgePersistentCache;
  final bool useTestFonts;
  final bool verboseSystemLogs;
  final int? hostVmServicePort;
  final int? deviceVmServicePort;
  final bool disablePortPublication;
  final int? ddsPort;
  final Uri? devToolsServerAddress;
  final bool? webEnableExposeUrl;
  final bool webUseSseForDebugProxy;
  final bool webUseSseForDebugBackend;
  final bool webUseSseForInjectedClient;
  final ImpellerStatus enableImpeller;
  final bool enableFlutterGpu;
  final bool enableVulkanValidation;
  final bool enableDartProfiling;
  final bool enableHcpp;
  final bool profileStartup;
  final bool enableEmbedderApi;
  final bool usingCISystem;
  final String? debugLogsDirectoryPath;
  final bool enableDevTools;
  final bool ipv6;
  final String? google3WorkspaceRoot;
  final bool printDtd;
  final WebDevServerConfig? webDevServerConfig;
  final bool testFlag;

  /// Whether the tool should try to uninstall a previously installed version of the app.
  ///
  /// This is not implemented for every platform.
  final bool uninstallFirst;

  /// Whether the tool should uninstall the app after running.
  ///
  /// This is currently only implemented for integration tests.
  /// Defaults to true.
  final bool uninstallApp;

  /// Whether to run the browser in headless mode.
  ///
  /// Some CI environments do not provide a display and fail to launch the
  /// browser with full graphics stack. Some browsers provide a special
  /// "headless" mode that runs the browser with no graphics.
  final bool webRunHeadless;

  /// The port the browser should use for its debugging protocol.
  final int? webBrowserDebugPort;

  /// Arbitrary browser flags.
  final List<String> webBrowserFlags;

  /// Enable expression evaluation for web target.
  final bool webEnableExpressionEvaluation;

  /// Allow developers to customize the browser's launch URL
  final String? webLaunchUrl;

  /// Whether to enable cross-origin isolation. This is on by default for the
  /// skwasm renderer.
  final bool webCrossOriginIsolation;

  /// Which web renderer to use for the debugging session
  final WebRendererMode webRenderer;

  /// Whether to compile to webassembly
  final bool webUseWasm;

  /// A file where the VM Service URL should be written after the application is started.
  final String? vmserviceOutFile;

  /// Additional null runtime checks inserted for web applications.
  ///
  /// See also:
  ///   * https://github.com/dart-lang/sdk/blob/main/sdk/lib/html/doc/NATIVE_NULL_ASSERTIONS.md
  final bool nativeNullAssertions;

  List<String> getIOSLaunchArguments(
    EnvironmentType environmentType,
    String? route,
    Map<String, Object?> platformArgs, {
    DeviceConnectionInterface interfaceType = DeviceConnectionInterface.attached,
  }) {
    return <String>[
      if (enableDartProfiling) '--enable-dart-profiling',
      if (profileStartup) '--profile-startup',
      if (disableServiceAuthCodes) '--disable-service-auth-codes',
      if (disablePortPublication) '--disable-vm-service-publication',
      if (startPaused) '--start-paused',
      // Wrap dart flags in quotes for physical devices
      if (environmentType == EnvironmentType.physical && dartFlags.isNotEmpty)
        '--dart-flags="$dartFlags"',
      if (environmentType == EnvironmentType.simulator && dartFlags.isNotEmpty)
        '--dart-flags=$dartFlags',
      if (useTestFonts) '--use-test-fonts',
      if (debuggingEnabled) ...<String>['--enable-checked-mode', '--verify-entry-points'],
      if (enableSoftwareRendering) '--enable-software-rendering',
      if (traceSystrace) '--trace-systrace',
      if (traceToFile != null) '--trace-to-file="$traceToFile"',
      if (skiaDeterministicRendering) '--skia-deterministic-rendering',
      if (traceSkia) '--trace-skia',
      if (traceAllowlist != null) '--trace-allowlist="$traceAllowlist"',
      if (traceSkiaAllowlist != null) '--trace-skia-allowlist="$traceSkiaAllowlist"',
      if (endlessTraceBuffer) '--endless-trace-buffer',
      if (profileMicrotasks) '--profile-microtasks',
      if (verboseSystemLogs) '--verbose-logging',
      if (purgePersistentCache) '--purge-persistent-cache',
      if (route != null) '--route=$route',
      if (platformArgs['trace-startup'] as bool? ?? false) '--trace-startup',
      if (enableImpeller == ImpellerStatus.enabled) '--enable-impeller=true',
      if (enableImpeller == ImpellerStatus.disabled) '--enable-impeller=false',
      if (enableFlutterGpu) '--enable-flutter-gpu',
      if (environmentType == EnvironmentType.physical && deviceVmServicePort != null)
        '--vm-service-port=$deviceVmServicePort',
      // The simulator "device" is actually on the host machine so no ports will be forwarded.
      // Use the suggested host port.
      if (environmentType == EnvironmentType.simulator && hostVmServicePort != null)
        '--vm-service-port=$hostVmServicePort',
      // Tell the VM service to listen on all interfaces, don't restrict to the loopback.
      if (interfaceType == DeviceConnectionInterface.wireless)
        '--vm-service-host=${ipv6 ? '::0' : '0.0.0.0'}',
      if (enableEmbedderApi) '--enable-embedder-api',
    ];
  }

  Map<String, Object?> toJson() => <String, Object?>{
    'debuggingEnabled': debuggingEnabled,
    'startPaused': startPaused,
    'dartFlags': dartFlags,
    'dartEntrypointArgs': dartEntrypointArgs,
    'disableServiceAuthCodes': disableServiceAuthCodes,
    'enableDds': enableDds,
    'cacheStartupProfile': cacheStartupProfile,
    'enableSoftwareRendering': enableSoftwareRendering,
    'skiaDeterministicRendering': skiaDeterministicRendering,
    'traceSkia': traceSkia,
    'traceAllowlist': traceAllowlist,
    'traceSkiaAllowlist': traceSkiaAllowlist,
    'traceSystrace': traceSystrace,
    'traceToFile': traceToFile,
    'endlessTraceBuffer': endlessTraceBuffer,
    'profileMicrotasks': profileMicrotasks,
    'purgePersistentCache': purgePersistentCache,
    'useTestFonts': useTestFonts,
    'verboseSystemLogs': verboseSystemLogs,
    'hostVmServicePort': hostVmServicePort,
    'deviceVmServicePort': deviceVmServicePort,
    'disablePortPublication': disablePortPublication,
    'ddsPort': ddsPort,
    'devToolsServerAddress': devToolsServerAddress.toString(),
    'port': webDevServerConfig?.port,
    'hostname': webDevServerConfig?.host,
    'tlsCertPath': webDevServerConfig?.https?.certPath,
    'tlsCertKeyPath': webDevServerConfig?.https?.certKeyPath,
    'webEnableExposeUrl': webEnableExposeUrl,
    'webUseSseForDebugProxy': webUseSseForDebugProxy,
    'webUseSseForDebugBackend': webUseSseForDebugBackend,
    'webUseSseForInjectedClient': webUseSseForInjectedClient,
    'webRunHeadless': webRunHeadless,
    'webBrowserDebugPort': webBrowserDebugPort,
    'webBrowserFlags': webBrowserFlags,
    'webEnableExpressionEvaluation': webEnableExpressionEvaluation,
    'webLaunchUrl': webLaunchUrl,
    'webCrossOriginIsolation': webCrossOriginIsolation,
    'webHeaders': webDevServerConfig?.headers ?? <String, String>{},
    'webRenderer': webRenderer.name,
    'webUseWasm': webUseWasm,
    'vmserviceOutFile': vmserviceOutFile,
    'nativeNullAssertions': nativeNullAssertions,
    'enableImpeller': enableImpeller.asBool,
    'enableFlutterGpu': enableFlutterGpu,
    'enableVulkanValidation': enableVulkanValidation,
    'uninstallApp': uninstallApp,
    'enableDartProfiling': enableDartProfiling,
    'enableHcpp': enableHcpp,
    'profileStartup': profileStartup,
    'enableEmbedderApi': enableEmbedderApi,
    'usingCISystem': usingCISystem,
    // TODO(bkonyi): remove once fg3 is updated.
    'fastStart': false,
    'debugLogsDirectoryPath': debugLogsDirectoryPath,
    'enableDevTools': enableDevTools,
    'ipv6': ipv6,
    'google3WorkspaceRoot': google3WorkspaceRoot,
    'printDtd': printDtd,
    // TODO(jsimmons): This field is required for backward compatibility with
    // the flutter_tools binary that is currently checked into Google3.
    // Remove this when that binary has been updated.
    'webUseLocalCanvaskit': false,
    // See above: these fields are required for backwards compatibility
    // with the google3 checked in binary.
    'dumpSkpOnShaderCompilation': false,
    'cacheSkSL': false,
  };

  static DebuggingOptions fromJson(Map<String, Object?> json, BuildInfo buildInfo) =>
      DebuggingOptions._(
        buildInfo: buildInfo,
        debuggingEnabled: json['debuggingEnabled']! as bool,
        startPaused: json['startPaused']! as bool,
        dartFlags: json['dartFlags']! as String,
        dartEntrypointArgs: (json['dartEntrypointArgs']! as List<dynamic>).cast<String>(),
        disableServiceAuthCodes: json['disableServiceAuthCodes']! as bool,
        enableDds: json['enableDds']! as bool,
        cacheStartupProfile: json['cacheStartupProfile']! as bool,
        enableSoftwareRendering: json['enableSoftwareRendering']! as bool,
        skiaDeterministicRendering: json['skiaDeterministicRendering']! as bool,
        traceSkia: json['traceSkia']! as bool,
        traceAllowlist: json['traceAllowlist'] as String?,
        traceSkiaAllowlist: json['traceSkiaAllowlist'] as String?,
        traceSystrace: json['traceSystrace']! as bool,
        traceToFile: json['traceToFile'] as String?,
        endlessTraceBuffer: json['endlessTraceBuffer']! as bool,
        profileMicrotasks: json['profileMicrotasks']! as bool,
        purgePersistentCache: json['purgePersistentCache']! as bool,
        useTestFonts: json['useTestFonts']! as bool,
        verboseSystemLogs: json['verboseSystemLogs']! as bool,
        hostVmServicePort: json['hostVmServicePort'] as int?,
        deviceVmServicePort: json['deviceVmServicePort'] as int?,
        disablePortPublication: json['disablePortPublication']! as bool,
        ddsPort: json['ddsPort'] as int?,
        devToolsServerAddress: json['devToolsServerAddress'] != null
            ? Uri.parse(json['devToolsServerAddress']! as String)
            : null,
        webEnableExposeUrl: json['webEnableExposeUrl'] as bool?,
        webUseSseForDebugProxy: json['webUseSseForDebugProxy']! as bool,
        webUseSseForDebugBackend: json['webUseSseForDebugBackend']! as bool,
        webUseSseForInjectedClient: json['webUseSseForInjectedClient']! as bool,
        webRunHeadless: json['webRunHeadless']! as bool,
        webBrowserDebugPort: json['webBrowserDebugPort'] as int?,
        webBrowserFlags: (json['webBrowserFlags']! as List<dynamic>).cast<String>(),
        webEnableExpressionEvaluation: json['webEnableExpressionEvaluation']! as bool,
        webLaunchUrl: json['webLaunchUrl'] as String?,
        webCrossOriginIsolation: json['webCrossOriginIsolation']! as bool,
        webRenderer: WebRendererMode.values.byName(json['webRenderer']! as String),
        webUseWasm: json['webUseWasm']! as bool,
        vmserviceOutFile: json['vmserviceOutFile'] as String?,
        nativeNullAssertions: json['nativeNullAssertions']! as bool,
        enableImpeller: ImpellerStatus.fromBool(json['enableImpeller'] as bool?),
        enableFlutterGpu: json['enableFlutterGpu']! as bool,
        enableVulkanValidation: (json['enableVulkanValidation'] as bool?) ?? false,
        uninstallFirst: (json['uninstallFirst'] as bool?) ?? false,
        uninstallApp: (json['uninstallApp'] as bool?) ?? true,
        enableDartProfiling: (json['enableDartProfiling'] as bool?) ?? true,
        enableHcpp: (json['enableHcpp'] as bool?) ?? false,
        profileStartup: (json['profileStartup'] as bool?) ?? false,
        enableEmbedderApi: (json['enableEmbedderApi'] as bool?) ?? false,
        usingCISystem: (json['usingCISystem'] as bool?) ?? false,
        debugLogsDirectoryPath: json['debugLogsDirectoryPath'] as String?,
        enableDevTools: (json['enableDevTools'] as bool?) ?? true,
        ipv6: (json['ipv6'] as bool?) ?? false,
        google3WorkspaceRoot: json['google3WorkspaceRoot'] as String?,
        printDtd: (json['printDtd'] as bool?) ?? false,
        webDevServerConfig: WebDevServerConfig(
          port: json['port'] is int ? json['port']! as int : 8080,
          host: json['hostname'] is String ? json['hostname']! as String : 'localhost',
          https: HttpsConfig.parse(json['tlsCertPath'], json['tlsCertKeyPath']),
          headers: (json['webHeaders']! as Map<dynamic, dynamic>).cast<String, String>(),
        ),
      );
}

class LaunchResult {
  LaunchResult.succeeded({this.vmServiceUri}) : started = true;

  LaunchResult.failed() : started = false, vmServiceUri = null;

  bool get hasVmService => vmServiceUri != null;

  final bool started;
  final Uri? vmServiceUri;

  @override
  String toString() {
    final buf = StringBuffer('started=$started');
    if (vmServiceUri != null) {
      buf.write(', vmService=$vmServiceUri');
    }
    return buf.toString();
  }
}

/// Read the log for a particular device.
abstract class DeviceLogReader {
  String get name;

  /// A broadcast stream where each element in the string is a line of log output.
  Stream<String> get logLines;

  /// Some logs can be obtained from a VM service stream.
  /// Set this after the VM services are connected.
  Future<void> provideVmService(FlutterVmService connectedVmService);

  @override
  String toString() => name;

  // Clean up resources allocated by log reader e.g. subprocesses
  void dispose();
}

/// Describes an app running on the device.
class DiscoveredApp {
  DiscoveredApp(this.id, this.vmServicePort);
  final String id;
  final int vmServicePort;
}

// An empty device log reader
class NoOpDeviceLogReader implements DeviceLogReader {
  NoOpDeviceLogReader(String? nameOrNull) : name = nameOrNull ?? '';

  @override
  final String name;

  @override
  Stream<String> get logLines => const Stream<String>.empty();

  @override
  void dispose() {}

  @override
  Future<void> provideVmService(FlutterVmService connectedVmService) async {}
}
