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

import 'dart:async';

import 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../application_package.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../bundle_builder.dart';
import '../convert.dart';
import '../device.dart';
import '../device_port_forwarder.dart';
import '../features.dart';
import '../project.dart';
import '../protocol_discovery.dart';
import 'custom_device_config.dart';
import 'custom_device_workflow.dart';
import 'custom_devices_config.dart';

/// Replace all occurrences of `${someName}` with the value found for that
/// name inside replacementValues or additionalReplacementValues.
///
/// The replacement value is first looked for in [replacementValues] and then
/// [additionalReplacementValues]. If no value is found, an empty string will be
/// substituted instead.
List<String> interpolateCommand(
  List<String> command,
  Map<String, String> replacementValues, {
  Map<String, String> additionalReplacementValues = const <String, String>{}
}) {
  return interpolateStringList(
    command,
    Map<String, String>.of(additionalReplacementValues)
      ..addAll(replacementValues)
  );
}

/// A log reader that can listen to a process' stdout / stderr or another log line
/// Stream.
class CustomDeviceLogReader extends DeviceLogReader {
  CustomDeviceLogReader(this.name);

  /// The name of the device this log reader is associated with.
  @override
  final String name;

  @visibleForTesting
  final StreamController<String> logLinesController = StreamController<String>.broadcast();

  @visibleForTesting
  final List<StreamSubscription<String>> subscriptions = <StreamSubscription<String>>[];

  /// Listen to [process]' stdout and stderr, decode them using [SystemEncoding]
  /// and add each decoded line to [logLines].
  ///
  /// However, [logLines] will not be done when the [process]' stdout and stderr
  /// streams are done. So [logLines] will still be alive after the process has
  /// finished.
  ///
  /// See [CustomDeviceLogReader.dispose] to end the [logLines] stream.
  void listenToProcessOutput(Process process, {Encoding encoding = systemEncoding}) {
    final Converter<List<int>, String> decoder = encoding.decoder;

    subscriptions.add(
      process.stdout.transform<String>(decoder)
        .transform<String>(const LineSplitter())
        .listen(logLinesController.add),
    );

    subscriptions.add(
      process.stderr.transform<String>(decoder)
        .transform<String>(const LineSplitter())
        .listen(logLinesController.add)
    );
  }

  /// Add all lines emitted by [lines] to this [CustomDeviceLogReader]s [logLines]
  /// stream.
  ///
  /// Similar to [listenToProcessOutput], [logLines] will not be marked as done
  /// when the argument stream is done.
  ///
  /// Useful when you want to combine the contents of multiple log readers.
  void listenToLinesStream(Stream<String> lines) {
    subscriptions.add(
      lines.listen(logLinesController.add)
    );
  }

  /// Dispose this log reader, freeing all associated resources and marking
  /// [logLines] as done.
  @override
  Future<void> dispose() async {
    final List<Future<void>> futures = <Future<void>>[];

    for (final StreamSubscription<String> subscription in subscriptions) {
      futures.add(subscription.cancel());
    }

    futures.add(logLinesController.close());

    await Future.wait(futures);
  }

  @override
  Stream<String> get logLines => logLinesController.stream;
}

/// A [DevicePortForwarder] that uses commands to forward / unforward a port.
class CustomDevicePortForwarder extends DevicePortForwarder {
  CustomDevicePortForwarder({
    required String deviceName,
    required List<String> forwardPortCommand,
    required RegExp forwardPortSuccessRegex,
    this.numTries,
    required ProcessManager processManager,
    required Logger logger,
    Map<String, String> additionalReplacementValues = const <String, String>{}
  }) : _deviceName = deviceName,
       _forwardPortCommand = forwardPortCommand,
       _forwardPortSuccessRegex = forwardPortSuccessRegex,
       _processManager = processManager,
       _processUtils = ProcessUtils(
         processManager: processManager,
         logger: logger
       ),
       _additionalReplacementValues = additionalReplacementValues;

  final String _deviceName;
  final List<String> _forwardPortCommand;
  final RegExp _forwardPortSuccessRegex;
  final ProcessManager _processManager;
  final ProcessUtils _processUtils;
  final int? numTries;
  final Map<String, String> _additionalReplacementValues;
  final List<ForwardedPort> _forwardedPorts = <ForwardedPort>[];

  @override
  Future<void> dispose() async {
    // copy the list so we don't modify it concurrently
    await Future.wait(List<ForwardedPort>.of(_forwardedPorts).map(unforward));
  }

  Future<ForwardedPort?> tryForward(int devicePort, int hostPort) async {
    final List<String> interpolated = interpolateCommand(
      _forwardPortCommand,
      <String, String>{
        'devicePort': '$devicePort',
        'hostPort': '$hostPort',
      },
      additionalReplacementValues: _additionalReplacementValues
    );

    // launch the forwarding command
    final Process process = await _processUtils.start(interpolated);

    final Completer<ForwardedPort?> completer = Completer<ForwardedPort?>();

    // read the outputs of the process, if we find a line that matches
    // the configs forwardPortSuccessRegex, we complete with a successfully
    // forwarded port
    // Note that if that regex never matches, this will potentially run forever
    // and the forwarding will never complete
    final CustomDeviceLogReader reader = CustomDeviceLogReader(_deviceName)..listenToProcessOutput(process);
    final StreamSubscription<String> logLinesSubscription = reader.logLines.listen((String line) {
      if (_forwardPortSuccessRegex.hasMatch(line) && !completer.isCompleted) {
        completer.complete(
          ForwardedPort.withContext(hostPort, devicePort, process)
        );
      }
    });

    // if the process exits (even with exitCode == 0), that is considered
    // a port forwarding failure and we complete with a null value.
    unawaited(process.exitCode.whenComplete(() {
      if (!completer.isCompleted) {
        completer.complete(null);
      }
    }));

    unawaited(completer.future.whenComplete(() {
      unawaited(logLinesSubscription.cancel());
      unawaited(reader.dispose());
    }));

    return completer.future;
  }

  @override
  Future<int> forward(int devicePort, {int? hostPort}) async {
    int actualHostPort = (hostPort == 0 || hostPort == null) ? devicePort : hostPort;
    int tries = 0;

    while ((numTries == null) || (tries < numTries!)) {
      // when the desired host port is already forwarded by this Forwarder,
      // choose another one
      while (_forwardedPorts.any((ForwardedPort port) => port.hostPort == actualHostPort)) {
        actualHostPort += 1;
      }

      final ForwardedPort? port = await tryForward(devicePort, actualHostPort);

      if (port != null) {
        _forwardedPorts.add(port);
        return actualHostPort;
      } else {
        // null value means the forwarding failed (for whatever reason)
        // increase port by one and try again
        actualHostPort += 1;
        tries += 1;
      }
    }

    throw ToolExit('Forwarding port for custom device $_deviceName failed after $tries tries.');
  }

  @override
  List<ForwardedPort> get forwardedPorts => List<ForwardedPort>.unmodifiable(_forwardedPorts);

  @override
  Future<void> unforward(ForwardedPort forwardedPort) async {
    assert(_forwardedPorts.contains(forwardedPort));

    // since a forwarded port represents a running process launched with
    // the forwardPortCommand, unforwarding is as easy as killing the process
    final int? pid = forwardedPort.context?.pid;
    if (pid != null) {
      _processManager.killPid(pid);
    }
    _forwardedPorts.remove(forwardedPort);
  }
}

/// A combination of [ApplicationPackage] and a [CustomDevice]. Can only start,
/// stop this specific app package with this specific device. Useful because we
/// often need to store additional context to an app that is running on a device,
/// like any forwarded ports we need to unforward later, the process we need to
/// kill to stop the app, maybe other things in the future.
class CustomDeviceAppSession {
  CustomDeviceAppSession({
    required this.name,
    required CustomDevice device,
    required ApplicationPackage appPackage,
    required Logger logger,
    required ProcessManager processManager
  }) : _appPackage = appPackage,
       _device = device,
       _logger = logger,
       _processManager = processManager,
       _processUtils = ProcessUtils(
         processManager: processManager,
         logger: logger
       ),
       logReader = CustomDeviceLogReader(name);

  final String name;
  final CustomDevice _device;
  final ApplicationPackage _appPackage;
  final Logger _logger;
  final ProcessManager _processManager;
  final ProcessUtils _processUtils;
  final CustomDeviceLogReader logReader;

  Process? _process;
  int? _forwardedHostPort;

  /// Get the engine options for the given [debuggingOptions],
  /// [traceStartup] and [route].
  ///
  /// [debuggingOptions] and [route] can be null.
  ///
  /// For example, `_getEngineOptions(null, false, null)` will return
  /// `['enable-dart-profiling=true']`
  List<String> _getEngineOptions(DebuggingOptions debuggingOptions, bool traceStartup, String? route) {
    final List<String> options = <String>[];

    void addFlag(String value) {
      options.add(value);
    }

    addFlag('enable-dart-profiling=true');

    if (traceStartup) {
      addFlag('trace-startup=true');
    }
    if (route != null) {
      addFlag('route=$route');
    }
    if (debuggingOptions != null) {
      if (debuggingOptions.enableSoftwareRendering) {
        addFlag('enable-software-rendering=true');
      }
      if (debuggingOptions.skiaDeterministicRendering) {
        addFlag('skia-deterministic-rendering=true');
      }
      if (debuggingOptions.traceSkia) {
        addFlag('trace-skia=true');
      }
      if (debuggingOptions.traceAllowlist != null) {
        addFlag('trace-allowlist=${debuggingOptions.traceAllowlist}');
      }
      if (debuggingOptions.traceSystrace) {
        addFlag('trace-systrace=true');
      }
      if (debuggingOptions.endlessTraceBuffer) {
        addFlag('endless-trace-buffer=true');
      }
      if (debuggingOptions.dumpSkpOnShaderCompilation) {
        addFlag('dump-skp-on-shader-compilation=true');
      }
      if (debuggingOptions.cacheSkSL) {
        addFlag('cache-sksl=true');
      }
      if (debuggingOptions.purgePersistentCache) {
        addFlag('purge-persistent-cache=true');
      }
      // Options only supported when there is a VM Service connection between the
      // tool and the device, usually in debug or profile mode.
      if (debuggingOptions.debuggingEnabled) {
        if (debuggingOptions.deviceVmServicePort != null) {
          addFlag('observatory-port=${debuggingOptions.deviceVmServicePort}');
        }
        if (debuggingOptions.buildInfo.isDebug) {
          addFlag('enable-checked-mode=true');
          addFlag('verify-entry-points=true');
        }
        if (debuggingOptions.startPaused) {
          addFlag('start-paused=true');
        }
        if (debuggingOptions.disableServiceAuthCodes) {
          addFlag('disable-service-auth-codes=true');
        }
        final String dartVmFlags = computeDartVmFlags(debuggingOptions);
        if (dartVmFlags.isNotEmpty) {
          addFlag('dart-flags=$dartVmFlags');
        }
        if (debuggingOptions.useTestFonts) {
          addFlag('use-test-fonts=true');
        }
        if (debuggingOptions.verboseSystemLogs) {
          addFlag('verbose-logging=true');
        }
      }
    }

    return options;
  }

  /// Get the engine options for the given [debuggingOptions],
  /// [traceStartup] and [route].
  ///
  /// [debuggingOptions] and [route] can be null.
  ///
  /// For example, `_getEngineOptionsForCmdline(null, false, null)` will return
  /// `--enable-dart-profiling=true`
  String _getEngineOptionsForCmdline(DebuggingOptions debuggingOptions, bool traceStartup, String? route) {
    return _getEngineOptions(debuggingOptions, traceStartup, route).map((String e) => '--$e').join(' ');
  }

  /// Start the app on the device.
  /// Needs the app to be installed on the device and not running already.
  ///
  /// [mainPath], [route], [debuggingOptions], [platformArgs] and
  /// [userIdentifier] may be null.
  ///
  /// [ipv6] may not be respected since it depends on the device config whether
  /// it uses ipv6 or ipv4
  Future<LaunchResult> start({
    String? mainPath,
    String? route,
    required DebuggingOptions debuggingOptions,
    Map<String, Object?> platformArgs = const <String, Object>{},
    bool prebuiltApplication = false,
    bool ipv6 = false,
    String? userIdentifier
  }) async {
    final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false;
    final String? packageName = _appPackage.name;
    if (packageName == null) {
      throw ToolExit('Could not start app, name for $_appPackage is unknown.');
    }
    final List<String> interpolated = interpolateCommand(
      _device._config.runDebugCommand,
      <String, String>{
        'remotePath': '/tmp/',
        'appName': packageName,
        'engineOptions': _getEngineOptionsForCmdline(debuggingOptions, traceStartup, route),
      }
    );

    final Process process = await _processUtils.start(interpolated);
    assert(_process == null);
    _process = process;

    final ProtocolDiscovery discovery = ProtocolDiscovery.observatory(
      logReader,
      portForwarder: _device._config.usesPortForwarding ? _device.portForwarder : null,
      logger: _logger,
      ipv6: ipv6,
    );

    // We need to make the discovery listen to the logReader before the logReader
    // listens to the process output since logReader.lines is a broadcast stream
    // and events may be discarded.
    // Whether that actually happens is another thing since this is all executed
    // in the same microtask AFAICT but this way we're on the safe side.
    logReader.listenToProcessOutput(process);

    final Uri? observatoryUri = await discovery.uri;
    await discovery.cancel();

    if (_device._config.usesPortForwarding) {
      _forwardedHostPort = observatoryUri?.port;
    }

    return LaunchResult.succeeded(observatoryUri: observatoryUri);
  }

  void _maybeUnforwardPort() {
    if (_forwardedHostPort != null) {
      final ForwardedPort forwardedPort = _device.portForwarder.forwardedPorts.singleWhere((ForwardedPort forwardedPort) {
        return forwardedPort.hostPort == _forwardedHostPort;
      });

      _forwardedHostPort = null;
      _device.portForwarder.unforward(forwardedPort);
    }
  }

  /// Stop the app on the device.
  /// Returns false if the app is not yet running. Also unforwards any
  /// forwarded ports.
  Future<bool> stop() async {
    if (_process == null) {
      return false;
    }

    _maybeUnforwardPort();
    final bool result = _processManager.killPid(_process!.pid);
    _process = null;
    return result;
  }

  void dispose() {
    if (_process != null) {
      _maybeUnforwardPort();
      _processManager.killPid(_process!.pid);
      _process = null;
    }

    unawaited(logReader.dispose());
  }
}

/// A device that uses user-configured actions for the common device methods.
/// The exact actions are defined by the contents of the [CustomDeviceConfig]
/// used to construct it.
class CustomDevice extends Device {
  CustomDevice({
    required CustomDeviceConfig config,
    required Logger logger,
    required ProcessManager processManager,
  }) : _config = config,
       _logger = logger,
       _processManager = processManager,
       _processUtils = ProcessUtils(
         processManager: processManager,
         logger: logger
       ),
       _globalLogReader = CustomDeviceLogReader(config.label),
       portForwarder = config.usesPortForwarding ?
         CustomDevicePortForwarder(
           deviceName: config.label,
           forwardPortCommand: config.forwardPortCommand!,
           forwardPortSuccessRegex: config.forwardPortSuccessRegex!,
           processManager: processManager,
           logger: logger,
         ) : const NoOpDevicePortForwarder(),
       super(
         config.id,
         category: Category.mobile,
         ephemeral: true,
         platformType: PlatformType.custom
       );

  final CustomDeviceConfig _config;
  final Logger _logger;
  final ProcessManager _processManager;
  final ProcessUtils _processUtils;
  final Map<ApplicationPackage, CustomDeviceAppSession> _sessions = <ApplicationPackage, CustomDeviceAppSession>{};
  final CustomDeviceLogReader _globalLogReader;

  @override
  final DevicePortForwarder portForwarder;

  CustomDeviceAppSession _getOrCreateAppSession(covariant ApplicationPackage app) {
    return _sessions.putIfAbsent(
      app,
      () {
        /// create a new session and add its logging to the global log reader.
        /// (needed bc it's possible the infra requests a global log in [getLogReader]
        final CustomDeviceAppSession session = CustomDeviceAppSession(
          name: name,
          device: this,
          appPackage: app,
          logger: _logger,
          processManager: _processManager
        );

        _globalLogReader.listenToLinesStream(session.logReader.logLines);

        return session;
      }
    );
  }

  /// Tries to ping the device using the ping command given in the config.
  /// All string interpolation occurrences inside the ping command will be replaced
  /// using the entries in [replacementValues].
  ///
  /// If the process finishes with an exit code != 0, false will be returned and
  /// the error (with the process' stdout and stderr) will be logged using
  /// [_logger.printError].
  ///
  /// If [timeout] is not null and the process doesn't finish in time,
  /// it will be killed with a SIGTERM, false will be returned and the timeout
  /// will be reported in the log using [_logger.printError]. If [timeout]
  /// is null, it's treated as if it's an infinite timeout.
  Future<bool> tryPing({
    Duration? timeout,
    Map<String, String> replacementValues = const <String, String>{}
  }) async {
    final List<String> interpolated = interpolateCommand(
      _config.pingCommand,
      replacementValues
    );

    final RunResult result = await _processUtils.run(
      interpolated,
      timeout: timeout
    );

    if (result.exitCode != 0) {
      return false;
    }

    // If the user doesn't configure a ping success regex, any ping with exitCode zero
    // is good enough. Otherwise we check if either stdout or stderr have a match of
    // the pingSuccessRegex.
    final RegExp? pingSuccessRegex = _config.pingSuccessRegex;
    return pingSuccessRegex == null
      || pingSuccessRegex.hasMatch(result.stdout)
      || pingSuccessRegex.hasMatch(result.stderr);
  }

  /// Tries to execute the configs postBuild command using [appName] for the
  /// `${appName}` and [localPath] for the `${localPath}` interpolations,
  /// any additional string interpolation occurrences will be replaced using the
  /// entries in [additionalReplacementValues].
  ///
  /// Calling this when the config doesn't have a configured postBuild command
  /// is an error.
  ///
  /// If [timeout] is not null and the process doesn't finish in time, it
  /// will be killed with a SIGTERM, false will be returned and the timeout
  /// will be reported in the log using [_logger.printError]. If [timeout]
  /// is null, it's treated as if it's an infinite timeout.
  Future<bool> _tryPostBuild({
    required String appName,
    required String localPath,
    Duration? timeout,
    Map<String, String> additionalReplacementValues = const <String, String>{}
  }) async {
    assert(_config.postBuildCommand != null);

    final List<String> interpolated = interpolateCommand(
      _config.postBuildCommand!,
      <String, String>{
        'appName': appName,
        'localPath': localPath,
      },
      additionalReplacementValues: additionalReplacementValues
    );

    try {
      await _processUtils.run(
        interpolated,
        throwOnError: true,
        timeout: timeout
      );
      return true;
    } on ProcessException catch (e) {
      _logger.printError('Error executing postBuild command for custom device $id: $e');
      return false;
    }
  }

  /// Tries to execute the configs uninstall command.
  ///
  /// [appName] is the name of the app to be installed.
  ///
  /// If [timeout] is not null and the process doesn't finish in time, it
  /// will be killed with a SIGTERM, false will be returned and the timeout
  /// will be reported in the log using [_logger.printError]. If [timeout]
  /// is null, it's treated as if it's an infinite timeout.
  Future<bool> tryUninstall({
    required String appName,
    Duration? timeout,
    Map<String, String> additionalReplacementValues = const <String, String>{}
  }) async {
    final List<String> interpolated = interpolateCommand(
      _config.uninstallCommand,
      <String, String>{
        'appName': appName,
      },
      additionalReplacementValues: additionalReplacementValues
    );

    try {
      await _processUtils.run(
        interpolated,
        throwOnError: true,
        timeout: timeout
      );
      return true;
    } on ProcessException catch (e) {
      _logger.printError('Error executing uninstall command for custom device $id: $e');
      return false;
    }
  }

  /// Tries to install the app to the custom device.
  ///
  /// [localPath] is the file / directory on the local device that will be
  /// copied over to the target custom device. This is substituted for any occurrence
  /// of `${localPath}` in the custom device configs `install` command.
  ///
  /// [appName] is the name of the app to be installed. Substituted for any occurrence
  /// of `${appName}` in the custom device configs `install` command.
  Future<bool> tryInstall({
    required String localPath,
    required String appName,
    Duration? timeout,
    Map<String, String> additionalReplacementValues = const <String, String>{}
  }) async {
    final List<String> interpolated = interpolateCommand(
      _config.installCommand,
      <String, String>{
        'localPath': localPath,
        'appName': appName,
      },
      additionalReplacementValues: additionalReplacementValues
    );

    try {
      await _processUtils.run(
        interpolated,
        throwOnError: true,
        timeout: timeout
      );

      return true;
    } on ProcessException catch (e) {
      _logger.printError('Error executing install command for custom device $id: $e');
      return false;
    }
  }

  @override
  void clearLogs() {}

  @override
  Future<void> dispose() async {
    _sessions
      ..forEach((_, CustomDeviceAppSession session) => session.dispose())
      ..clear();
  }

  @override
  Future<String?> get emulatorId async => null;

  @override
  FutureOr<DeviceLogReader> getLogReader({
    covariant ApplicationPackage? app,
    bool includePastLogs = false
  }) {
    if (app != null) {
      return _getOrCreateAppSession(app).logReader;
    }

    return _globalLogReader;
  }

  @override
  Future<bool> installApp(covariant ApplicationPackage app, {String? userIdentifier}) async {
    final String? appName = app.name;
    if (appName == null || !await tryUninstall(appName: appName)) {
      return false;
    }

    final bool result = await tryInstall(
      localPath: getAssetBuildDirectory(),
      appName: appName,
    );

    return result;
  }

  @override
  Future<bool> isAppInstalled(covariant ApplicationPackage app, {String? userIdentifier}) async {
    return false;
  }

  @override
  Future<bool> isLatestBuildInstalled(covariant ApplicationPackage app) async {
    return false;
  }

  @override
  Future<bool> get isLocalEmulator async => false;

  @override
  bool get supportsScreenshot => _config.supportsScreenshotting;

  @override
  Future<void> takeScreenshot(File outputFile) async {
    if (supportsScreenshot == false) {
      throw UnsupportedError('Screenshotting is not supported for this device.');
    }

    final List<String> interpolated = interpolateCommand(
      _config.screenshotCommand!,
      <String, String>{},
    );

    final RunResult result = await _processUtils.run(interpolated, throwOnError: true);
    await outputFile.writeAsBytes(base64Decode(result.stdout));
  }

  @override
  bool isSupported() {
    return true;
  }

  @override
  bool isSupportedForProject(FlutterProject flutterProject) {
    return true;
  }

  @override
  FutureOr<bool> supportsRuntimeMode(BuildMode buildMode) {
    return buildMode == BuildMode.debug;
  }

  @override
  String get name => _config.label;

  @override
  Future<String> get sdkNameAndVersion => Future<String>.value(_config.sdkNameAndVersion);

  @override
  Future<LaunchResult> startApp(
    covariant ApplicationPackage package, {
    String? mainPath,
    String? route,
    required DebuggingOptions debuggingOptions,
    Map<String, Object?> platformArgs = const <String, Object>{},
    bool prebuiltApplication = false,
    bool ipv6 = false,
    String? userIdentifier,
    BundleBuilder? bundleBuilder,
  }) async {
    if (!prebuiltApplication) {
      final String assetBundleDir = getAssetBuildDirectory();

      bundleBuilder ??= BundleBuilder();

      // this just builds the asset bundle, it's the same as `flutter build bundle`
      await bundleBuilder.build(
        platform: await targetPlatform,
        buildInfo: debuggingOptions.buildInfo,
        mainPath: mainPath,
        depfilePath: defaultDepfilePath,
        assetDirPath: assetBundleDir,
      );

      // if we have a post build step (needed for some embedders), execute it
      if (_config.postBuildCommand != null) {
        final String? packageName = package.name;
        if (packageName == null) {
          throw ToolExit('Could not start app, name for $package is unknown.');
        }
        await _tryPostBuild(
          appName: packageName,
          localPath: assetBundleDir,
        );
      }
    }

    // install the app on the device
    // (will invoke the uninstall and then the install command internally)
    await installApp(package, userIdentifier: userIdentifier);

    // finally launch the app
    return _getOrCreateAppSession(package).start(
      mainPath: mainPath,
      route: route,
      debuggingOptions: debuggingOptions,
      platformArgs: platformArgs,
      prebuiltApplication: prebuiltApplication,
      ipv6: ipv6,
      userIdentifier: userIdentifier,
    );
  }

  @override
  Future<bool> stopApp(covariant ApplicationPackage app, {String? userIdentifier}) {
    return _getOrCreateAppSession(app).stop();
  }

  @override
  Future<TargetPlatform> get targetPlatform async => _config.platform ?? TargetPlatform.linux_arm64;

  @override
  Future<bool> uninstallApp(covariant ApplicationPackage app, {String? userIdentifier}) async {
    final String? appName = app.name;
    if (appName == null) {
      return false;
    }
    return tryUninstall(appName: appName);
  }
}

/// A [PollingDeviceDiscovery] that'll try to ping all enabled devices in the argument
/// [CustomDevicesConfig] and report the ones that were actually reachable.
class CustomDevices extends PollingDeviceDiscovery {
  /// Create a custom device discovery that pings all enabled devices in the
  /// given [CustomDevicesConfig].
  CustomDevices({
    required FeatureFlags featureFlags,
    required ProcessManager processManager,
    required Logger logger,
    required CustomDevicesConfig config
  }) : _customDeviceWorkflow = CustomDeviceWorkflow(
         featureFlags: featureFlags,
       ),
       _logger = logger,
       _processManager = processManager,
       _config = config,
       super('custom devices');

  final CustomDeviceWorkflow  _customDeviceWorkflow;
  final ProcessManager _processManager;
  final Logger _logger;
  final CustomDevicesConfig _config;

  @override
  bool get supportsPlatform => true;

  @override
  bool get canListAnything => _customDeviceWorkflow.canListDevices;

  CustomDevicesConfig get _customDevicesConfig => _config;

  List<CustomDevice> get _enabledCustomDevices {
    return _customDevicesConfig.tryGetDevices()
      .where((CustomDeviceConfig element) => element.enabled)
      .map(
        (CustomDeviceConfig config) => CustomDevice(
          config: config,
          logger: _logger,
          processManager: _processManager
        )
      ).toList();
  }

  @override
  Future<List<Device>> pollingGetDevices({Duration? timeout}) async {
    if (!canListAnything) {
      return const <Device>[];
    }

    final List<CustomDevice> devices = _enabledCustomDevices;

    // maps any custom device to whether its reachable or not.
    final Map<CustomDevice, bool> pingedDevices = Map<CustomDevice, bool>.fromIterables(
      devices,
      await Future.wait(devices.map((CustomDevice e) => e.tryPing(timeout: timeout)))
    );

    // remove all the devices we couldn't reach.
    pingedDevices.removeWhere((_, bool value) => value == false);

    // return only the devices.
    return pingedDevices.keys.toList();
  }

  @override
  Future<List<String>> getDiagnostics() async => const <String>[];

  @override
  List<String> get wellKnownIds => const <String>[];
}
