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

import '../base/common.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/terminal.dart';
import '../device.dart';
import '../globals.dart' as globals;
import '../ios/devices.dart';

const String _checkingForWirelessDevicesMessage = 'Checking for wireless devices...';
const String _chooseOneMessage = 'Please choose one (or "q" to quit)';
const String _connectedDevicesMessage = 'Connected devices:';
const String _foundButUnsupportedDevicesMessage = 'The following devices were found, but are not supported by this project:';
const String _noAttachedCheckForWirelessMessage = 'No devices found yet. Checking for wireless devices...';
const String _noDevicesFoundMessage = 'No devices found.';
const String _noWirelessDevicesFoundMessage = 'No wireless devices were found.';
const String _wirelesslyConnectedDevicesMessage = 'Wirelessly connected devices:';

String _chooseDeviceOptionMessage(int option, String name, String deviceId) => '[$option]: $name ($deviceId)';
String _foundMultipleSpecifiedDevicesMessage(String deviceId) =>
    'Found multiple devices with name or id matching $deviceId:';
String _foundSpecifiedDevicesMessage(int count, String deviceId) =>
    'Found $count devices with name or id matching $deviceId:';
String _noMatchingDeviceMessage(String deviceId) => 'No supported devices found with name or id '
    "matching '$deviceId'.";
String flutterSpecifiedDeviceDevModeDisabled(String deviceName) => 'To use '
    "'$deviceName' for development, enable Developer Mode in Settings → Privacy & Security.";
String flutterSpecifiedDeviceUnpaired(String deviceName) => "'$deviceName' is not paired. "
    'Open Xcode and trust this computer when prompted.';

/// This class handles functionality of finding and selecting target devices.
///
/// Target devices are devices that are supported and selectable to run
/// a flutter application on.
class TargetDevices {
  factory TargetDevices({
    required Platform platform,
    required DeviceManager deviceManager,
    required Logger logger,
    DeviceConnectionInterface? deviceConnectionInterface,
  }) {
    if (platform.isMacOS) {
      return TargetDevicesWithExtendedWirelessDeviceDiscovery(
        deviceManager: deviceManager,
        logger: logger,
        deviceConnectionInterface: deviceConnectionInterface,
      );
    }
    return TargetDevices._private(
      deviceManager: deviceManager,
      logger: logger,
      deviceConnectionInterface: deviceConnectionInterface,
    );
  }

  TargetDevices._private({
    required DeviceManager deviceManager,
    required Logger logger,
    required this.deviceConnectionInterface,
  })  : _deviceManager = deviceManager,
        _logger = logger;

  final DeviceManager _deviceManager;
  final Logger _logger;
  final DeviceConnectionInterface? deviceConnectionInterface;

  bool get _includeAttachedDevices =>
      deviceConnectionInterface == null ||
      deviceConnectionInterface == DeviceConnectionInterface.attached;
  bool get _includeWirelessDevices =>
      deviceConnectionInterface == null ||
      deviceConnectionInterface == DeviceConnectionInterface.wireless;

  Future<List<Device>> _getAttachedDevices({
    DeviceDiscoverySupportFilter? supportFilter,
  }) async {
    if (!_includeAttachedDevices) {
      return <Device>[];
    }
    return _deviceManager.getDevices(
      filter: DeviceDiscoveryFilter(
        deviceConnectionInterface: DeviceConnectionInterface.attached,
        supportFilter: supportFilter,
      ),
    );
  }

  Future<List<Device>> _getWirelessDevices({
    DeviceDiscoverySupportFilter? supportFilter,
  }) async {
    if (!_includeWirelessDevices) {
      return <Device>[];
    }
    return _deviceManager.getDevices(
      filter: DeviceDiscoveryFilter(
        deviceConnectionInterface: DeviceConnectionInterface.wireless,
        supportFilter: supportFilter,
      ),
    );
  }

  Future<List<Device>> _getDeviceById({
    bool includeDevicesUnsupportedByProject = false,
    bool includeDisconnected = false,
  }) async {
    return _deviceManager.getDevices(
      filter: DeviceDiscoveryFilter(
        excludeDisconnected: !includeDisconnected,
        supportFilter: _deviceManager.deviceSupportFilter(
          includeDevicesUnsupportedByProject: includeDevicesUnsupportedByProject,
        ),
        deviceConnectionInterface: deviceConnectionInterface,
      ),
    );
  }

  DeviceDiscoverySupportFilter _defaultSupportFilter(
    bool includeDevicesUnsupportedByProject,
  ) {
    return _deviceManager.deviceSupportFilter(
      includeDevicesUnsupportedByProject: includeDevicesUnsupportedByProject,
    );
  }

  void startExtendedWirelessDeviceDiscovery({
    Duration? deviceDiscoveryTimeout,
  }) {}

  /// Find and return all target [Device]s based upon criteria entered by the
  /// user on the command line.
  ///
  /// When the user has specified `all` devices, return all devices meeting criteria.
  ///
  /// When the user has specified a device id/name, attempt to find an exact or
  /// partial match. If an exact match or a single partial match is found,
  /// return it immediately.
  ///
  /// When multiple devices are found and there is a terminal attached to
  /// stdin, allow the user to select which device to use. When a terminal
  /// with stdin is not available, print a list of available devices and
  /// return null.
  ///
  /// When no devices meet user specifications, print a list of unsupported
  /// devices and return null.
  Future<List<Device>?> findAllTargetDevices({
    Duration? deviceDiscoveryTimeout,
    bool includeDevicesUnsupportedByProject = false,
  }) async {
    if (!globals.doctor!.canLaunchAnything) {
      _logger.printError(globals.userMessages.flutterNoDevelopmentDevice);
      return null;
    }

    if (deviceDiscoveryTimeout != null) {
      // Reset the cache with the specified timeout.
      await _deviceManager.refreshAllDevices(timeout: deviceDiscoveryTimeout);
    }

    if (_deviceManager.hasSpecifiedDeviceId) {
      // Must check for device match separately from `_getAttachedDevices` and
      // `_getWirelessDevices` because if an exact match is found in one
      // and a partial match is found in another, there is no way to distinguish
      // between them.
      final List<Device> devices = await _getDeviceById(
        includeDevicesUnsupportedByProject: includeDevicesUnsupportedByProject,
      );
      if (devices.length == 1) {
        return devices;
      }
    }

    final List<Device> attachedDevices = await _getAttachedDevices(
      supportFilter: _defaultSupportFilter(includeDevicesUnsupportedByProject),
    );
    final List<Device> wirelessDevices = await _getWirelessDevices(
      supportFilter: _defaultSupportFilter(includeDevicesUnsupportedByProject),
    );
    final List<Device> allDevices = attachedDevices + wirelessDevices;

    if (allDevices.isEmpty) {
      return _handleNoDevices();
    } else if (_deviceManager.hasSpecifiedAllDevices) {
      return allDevices;
    } else if (allDevices.length > 1) {
      return _handleMultipleDevices(attachedDevices, wirelessDevices);
    }
    return allDevices;
  }

  /// When no supported devices are found, display a message and list of
  /// unsupported devices found.
  Future<List<Device>?> _handleNoDevices() async {
    // Get connected devices from cache, including unsupported ones.
    final List<Device> unsupportedDevices = await _deviceManager.getAllDevices(
      filter: DeviceDiscoveryFilter(
        deviceConnectionInterface: deviceConnectionInterface,
      )
    );

    if (_deviceManager.hasSpecifiedDeviceId) {
      _logger.printStatus(
        _noMatchingDeviceMessage(_deviceManager.specifiedDeviceId!),
      );
      if (unsupportedDevices.isNotEmpty) {
        _logger.printStatus('');
        _logger.printStatus('The following devices were found:');
        await Device.printDevices(unsupportedDevices, _logger);
      }
      return null;
    }

    _logger.printStatus(_deviceManager.hasSpecifiedAllDevices
        ? _noDevicesFoundMessage
        : globals.userMessages.flutterNoSupportedDevices);
    await _printUnsupportedDevice(unsupportedDevices);
    return null;
  }

  /// Determine which device to use when multiple found.
  ///
  /// If user has not specified a device id/name, attempt to prioritize
  /// ephemeral devices. If a single ephemeral device is found, return it
  /// immediately.
  ///
  /// Otherwise, prompt the user to select a device if there is a terminal
  /// with stdin. If there is not a terminal, display the list of devices with
  /// instructions to use a device selection flag.
  Future<List<Device>?> _handleMultipleDevices(
    List<Device> attachedDevices,
    List<Device> wirelessDevices,
  ) async {
    final List<Device> allDevices = attachedDevices + wirelessDevices;

    final Device? ephemeralDevice = _deviceManager.getSingleEphemeralDevice(allDevices);
    if (ephemeralDevice != null) {
      return <Device>[ephemeralDevice];
    }

    if (globals.terminal.stdinHasTerminal) {
      return _selectFromMultipleDevices(attachedDevices, wirelessDevices);
    } else {
      return _printMultipleDevices(attachedDevices, wirelessDevices);
    }
  }

  /// Display a list of found devices. When the user has not specified the
  /// device id/name, display devices unsupported by the project as well and
  /// give instructions to use a device selection flag.
  Future<List<Device>?> _printMultipleDevices(
    List<Device> attachedDevices,
    List<Device> wirelessDevices,
  ) async {
    List<Device> supportedAttachedDevices = attachedDevices;
    List<Device> supportedWirelessDevices = wirelessDevices;
    if (_deviceManager.hasSpecifiedDeviceId) {
      final int allDeviceLength = supportedAttachedDevices.length + supportedWirelessDevices.length;
      _logger.printStatus(_foundSpecifiedDevicesMessage(
        allDeviceLength,
        _deviceManager.specifiedDeviceId!,
      ));
    } else {
      // Get connected devices from cache, including ones unsupported for the
      // project but still supported by Flutter.
      supportedAttachedDevices = await _getAttachedDevices(
        supportFilter: DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutter(),
      );
      supportedWirelessDevices = await _getWirelessDevices(
        supportFilter: DeviceDiscoverySupportFilter.excludeDevicesUnsupportedByFlutter(),
      );

      _logger.printStatus(globals.userMessages.flutterSpecifyDeviceWithAllOption);
      _logger.printStatus('');
    }

    await Device.printDevices(supportedAttachedDevices, _logger);

    if (supportedWirelessDevices.isNotEmpty) {
      if (_deviceManager.hasSpecifiedDeviceId || supportedAttachedDevices.isNotEmpty) {
        _logger.printStatus('');
      }
      _logger.printStatus(_wirelesslyConnectedDevicesMessage);
      await Device.printDevices(supportedWirelessDevices, _logger);
    }

    return null;
  }

  /// Display a list of selectable devices, prompt the user to choose one, and
  /// wait for the user to select a valid option.
  Future<List<Device>?> _selectFromMultipleDevices(
    List<Device> attachedDevices,
    List<Device> wirelessDevices,
  ) async {
    final List<Device> allDevices = attachedDevices + wirelessDevices;

    if (_deviceManager.hasSpecifiedDeviceId) {
      _logger.printStatus(_foundSpecifiedDevicesMessage(
        allDevices.length,
        _deviceManager.specifiedDeviceId!,
      ));
    } else {
      _logger.printStatus(_connectedDevicesMessage);
    }

    await Device.printDevices(attachedDevices, _logger);

    if (wirelessDevices.isNotEmpty) {
      _logger.printStatus('');
      _logger.printStatus(_wirelesslyConnectedDevicesMessage);
      await Device.printDevices(wirelessDevices, _logger);
      _logger.printStatus('');
    }

    final Device chosenDevice = await _chooseOneOfAvailableDevices(allDevices);

    // Update the [DeviceManager.specifiedDeviceId] so that the user will not
    // be prompted again.
    _deviceManager.specifiedDeviceId = chosenDevice.id;

    return <Device>[chosenDevice];
  }

  Future<void> _printUnsupportedDevice(List<Device> unsupportedDevices) async {
    if (unsupportedDevices.isNotEmpty) {
      final StringBuffer result = StringBuffer();
      result.writeln();
      result.writeln(_foundButUnsupportedDevicesMessage);
      result.writeAll(
        (await Device.descriptions(unsupportedDevices))
            .map((String desc) => desc)
            .toList(),
        '\n',
      );
      result.writeln();
      result.writeln(globals.userMessages.flutterMissPlatformProjects(
        Device.devicesPlatformTypes(unsupportedDevices),
      ));
      _logger.printStatus(result.toString(), newline: false);
    }
  }

  Future<Device> _chooseOneOfAvailableDevices(List<Device> devices) async {
    _displayDeviceOptions(devices);
    final String userInput =  await _readUserInput(devices.length);
    if (userInput.toLowerCase() == 'q') {
      throwToolExit('');
    }
    return devices[int.parse(userInput) - 1];
  }

  void _displayDeviceOptions(List<Device> devices) {
    int count = 1;
    for (final Device device in devices) {
      _logger.printStatus(_chooseDeviceOptionMessage(count, device.name, device.id));
      count++;
    }
  }

  Future<String> _readUserInput(int deviceCount) async {
    globals.terminal.usesTerminalUi = true;
    final String result = await globals.terminal.promptForCharInput(
      <String>[ for (int i = 0; i < deviceCount; i++) '${i + 1}', 'q', 'Q'],
      displayAcceptedCharacters: false,
      logger: _logger,
      prompt: _chooseOneMessage,
    );
    return result;
  }
}

@visibleForTesting
class TargetDevicesWithExtendedWirelessDeviceDiscovery extends TargetDevices {
  TargetDevicesWithExtendedWirelessDeviceDiscovery({
    required super.deviceManager,
    required super.logger,
    super.deviceConnectionInterface,
  })  : super._private();

  Future<void>? _wirelessDevicesRefresh;

  @visibleForTesting
  bool waitForWirelessBeforeInput = false;

  @visibleForTesting
  late final TargetDeviceSelection deviceSelection = TargetDeviceSelection(_logger);

  @override
  void startExtendedWirelessDeviceDiscovery({
    Duration? deviceDiscoveryTimeout,
  }) {
    if (deviceDiscoveryTimeout == null && _includeWirelessDevices) {
      _wirelessDevicesRefresh ??= _deviceManager.refreshExtendedWirelessDeviceDiscoverers(
        timeout: DeviceManager.minimumWirelessDeviceDiscoveryTimeout,
      );
    }
    return;
  }

  Future<List<Device>> _getRefreshedWirelessDevices({
    bool includeDevicesUnsupportedByProject = false,
  }) async {
    if (!_includeWirelessDevices) {
      return <Device>[];
    }
    startExtendedWirelessDeviceDiscovery();
    return () async {
      await _wirelessDevicesRefresh;
      return _deviceManager.getDevices(
        filter: DeviceDiscoveryFilter(
          deviceConnectionInterface: DeviceConnectionInterface.wireless,
          supportFilter: _defaultSupportFilter(includeDevicesUnsupportedByProject),
        ),
      );
    }();
  }

  Future<Device?> _waitForIOSDeviceToConnect(IOSDevice device) async {
    for (final DeviceDiscovery discoverer in _deviceManager.deviceDiscoverers) {
      if (discoverer is IOSDevices) {
        _logger.printStatus('Waiting for ${device.name} to connect...');
        final Status waitingStatus = _logger.startSpinner(
          timeout: const Duration(seconds: 30),
          warningColor: TerminalColor.red,
          slowWarningCallback: () {
            return 'The device was unable to connect after 30 seconds. Ensure the device is paired and unlocked.';
          },
        );
        final Device? connectedDevice = await discoverer.waitForDeviceToConnect(device, _logger);
        waitingStatus.stop();
        return connectedDevice;
      }
    }
    return null;
  }

  /// Find and return all target [Device]s based upon criteria entered by the
  /// user on the command line.
  ///
  /// When the user has specified `all` devices, return all devices meeting criteria.
  ///
  /// When the user has specified a device id/name, attempt to find an exact or
  /// partial match. If an exact match or a single partial match is found and
  /// the device is connected, return it immediately. If an exact match or a
  /// single partial match is found and the device is not connected and it's
  /// an iOS device, wait for it to connect.
  ///
  /// When multiple devices are found and there is a terminal attached to
  /// stdin, allow the user to select which device to use. When a terminal
  /// with stdin is not available, print a list of available devices and
  /// return null.
  ///
  /// When no devices meet user specifications, print a list of unsupported
  /// devices and return null.
  @override
  Future<List<Device>?> findAllTargetDevices({
    Duration? deviceDiscoveryTimeout,
    bool includeDevicesUnsupportedByProject = false,
  }) async {
    if (!globals.doctor!.canLaunchAnything) {
      _logger.printError(globals.userMessages.flutterNoDevelopmentDevice);
      return null;
    }

    // When a user defines the timeout or filters to only attached devices,
    // use the super function that does not do longer wireless device
    // discovery and does not wait for devices to connect.
    if (deviceDiscoveryTimeout != null || deviceConnectionInterface == DeviceConnectionInterface.attached) {
      return super.findAllTargetDevices(
        deviceDiscoveryTimeout: deviceDiscoveryTimeout,
        includeDevicesUnsupportedByProject: includeDevicesUnsupportedByProject,
      );
    }

    // Start polling for wireless devices that need longer to load if it hasn't
    // already been started.
    startExtendedWirelessDeviceDiscovery();

    if (_deviceManager.hasSpecifiedDeviceId) {
      // Get devices matching the specified device regardless of whether they
      // are currently connected or not.
      // If there is a single matching connected device, return it immediately.
      // If the only device found is an iOS device that is not connected yet,
      // wait for it to connect.
      // If there are multiple matches, continue on to wait for all attached
      // and wireless devices to load so the user can select between all
      // connected matches.
      final List<Device> specifiedDevices = await _getDeviceById(
        includeDevicesUnsupportedByProject: includeDevicesUnsupportedByProject,
        includeDisconnected: true,
      );

      if (specifiedDevices.length == 1) {
        Device? matchedDevice = specifiedDevices.first;
        if (matchedDevice is IOSDevice) {
          // If the only matching device is not paired, print a warning
          if (!matchedDevice.isPaired) {
            _logger.printStatus(flutterSpecifiedDeviceUnpaired(matchedDevice.name));
            return null;
          }
          // If the only matching device does not have Developer Mode enabled,
          // print a warning
          if (!matchedDevice.devModeEnabled) {
            _logger.printStatus(
                flutterSpecifiedDeviceDevModeDisabled(matchedDevice.name)
            );
            return null;
          }

          if (!matchedDevice.isConnected) {
            matchedDevice = await _waitForIOSDeviceToConnect(matchedDevice);
          }
        }

        if (matchedDevice != null && matchedDevice.isConnected) {
          return <Device>[matchedDevice];
        }

      } else {
        for (final IOSDevice device in specifiedDevices.whereType<IOSDevice>()) {
          // Print warning for every matching unpaired device.
          if (!device.isPaired) {
            _logger.printStatus(flutterSpecifiedDeviceUnpaired(device.name));
          }

          // Print warning for every matching device that does not have Developer Mode enabled.
          if (!device.devModeEnabled) {
            _logger.printStatus(
                flutterSpecifiedDeviceDevModeDisabled(device.name)
            );
          }
        }
      }
    }

    final List<Device> attachedDevices = await _getAttachedDevices(
      supportFilter: _defaultSupportFilter(includeDevicesUnsupportedByProject),
    );

    // _getRefreshedWirelessDevices must be run after _getAttachedDevices is
    // finished to prevent non-iOS discoverers from running simultaneously.
    // `AndroidDevices` may error if run simultaneously.
    final Future<List<Device>> futureWirelessDevices = _getRefreshedWirelessDevices(
      includeDevicesUnsupportedByProject: includeDevicesUnsupportedByProject,
    );

    if (attachedDevices.isEmpty) {
      return _handleNoAttachedDevices(attachedDevices, futureWirelessDevices);
    } else if (_deviceManager.hasSpecifiedAllDevices) {
      return _handleAllDevices(attachedDevices, futureWirelessDevices);
    }
    // Even if there's only a single attached device, continue to
    // `_handleRemainingDevices` since there might be wireless devices
    // that are not loaded yet.
    return _handleRemainingDevices(attachedDevices, futureWirelessDevices);
  }

  /// When no supported attached devices are found, wait for wireless devices
  /// to load.
  ///
  /// If no wireless devices are found, continue to `_handleNoDevices`.
  ///
  /// If wireless devices are found, continue to `_handleMultipleDevices`.
  Future<List<Device>?> _handleNoAttachedDevices(
    List<Device> attachedDevices,
    Future<List<Device>> futureWirelessDevices,
  ) async {
    if (_includeAttachedDevices) {
      _logger.printStatus(_noAttachedCheckForWirelessMessage);
    } else {
      _logger.printStatus(_checkingForWirelessDevicesMessage);
    }

    final List<Device> wirelessDevices = await futureWirelessDevices;
    final List<Device> allDevices = attachedDevices + wirelessDevices;

    if (allDevices.isEmpty) {
      _logger.printStatus('');
      return _handleNoDevices();
    } else if (_deviceManager.hasSpecifiedAllDevices) {
      return allDevices;
    } else if (allDevices.length > 1) {
      _logger.printStatus('');
      return _handleMultipleDevices(attachedDevices, wirelessDevices);
    }
    return allDevices;
  }

  /// Wait for wireless devices to load and then return all attached and
  /// wireless devices.
  Future<List<Device>?> _handleAllDevices(
    List<Device> devices,
    Future<List<Device>> futureWirelessDevices,
  ) async {
    _logger.printStatus(_checkingForWirelessDevicesMessage);
    final List<Device> wirelessDevices = await futureWirelessDevices;
    return devices + wirelessDevices;
  }

  /// Determine which device to use when one or more are found.
  ///
  /// If user has not specified a device id/name, attempt to prioritize
  /// ephemeral devices. If a single ephemeral device is found, return it
  /// immediately.
  ///
  /// Otherwise, prompt the user to select a device if there is a terminal
  /// with stdin. If there is not a terminal, display the list of devices with
  /// instructions to use a device selection flag.
  Future<List<Device>?> _handleRemainingDevices(
    List<Device> attachedDevices,
    Future<List<Device>> futureWirelessDevices,
  ) async {
    final Device? ephemeralDevice = _deviceManager.getSingleEphemeralDevice(attachedDevices);
    if (ephemeralDevice != null) {
      return <Device>[ephemeralDevice];
    }

    if (!globals.terminal.stdinHasTerminal || !_logger.supportsColor) {
      _logger.printStatus(_checkingForWirelessDevicesMessage);
      final List<Device> wirelessDevices = await futureWirelessDevices;
      if (attachedDevices.length + wirelessDevices.length == 1) {
        return attachedDevices + wirelessDevices;
      }
      _logger.printStatus('');
      // If the terminal has stdin but does not support color/ANSI (which is
      // needed to clear lines), fallback to standard selection of device.
      if (globals.terminal.stdinHasTerminal && !_logger.supportsColor) {
        return _handleMultipleDevices(attachedDevices, wirelessDevices);
      }
      // If terminal does not have stdin, print out device list.
      return _printMultipleDevices(attachedDevices, wirelessDevices);
    }

    return _selectFromDevicesAndCheckForWireless(
      attachedDevices,
      futureWirelessDevices,
    );
  }

  /// Display a list of selectable attached devices and prompt the user to
  /// choose one.
  ///
  /// Also, display a message about waiting for wireless devices to load. Once
  /// wireless devices have loaded, update waiting message, device list, and
  /// selection options.
  ///
  /// Wait for the user to select a device.
  Future<List<Device>?> _selectFromDevicesAndCheckForWireless(
    List<Device> attachedDevices,
    Future<List<Device>> futureWirelessDevices,
  ) async {
    if (attachedDevices.length == 1 || !_deviceManager.hasSpecifiedDeviceId) {
      _logger.printStatus(_connectedDevicesMessage);
    } else if (_deviceManager.hasSpecifiedDeviceId) {
      // Multiple devices were found with part of the name/id provided.
      _logger.printStatus(_foundMultipleSpecifiedDevicesMessage(
        _deviceManager.specifiedDeviceId!,
      ));
    }

    // Display list of attached devices.
    await Device.printDevices(attachedDevices, _logger);

    // Display waiting message.
    _logger.printStatus('');
    _logger.printStatus(_checkingForWirelessDevicesMessage);
    _logger.printStatus('');

    // Start user device selection so user can select device while waiting
    // for wireless devices to load if they want.
    _displayDeviceOptions(attachedDevices);
    deviceSelection.devices = attachedDevices;
    final Future<Device> futureChosenDevice = deviceSelection.userSelectDevice();
    Device? chosenDevice;

    // Once wireless devices are found, we clear out the waiting message (3),
    // device option list (attachedDevices.length), and device option prompt (1).
    int numLinesToClear = attachedDevices.length + 4;

    futureWirelessDevices = futureWirelessDevices.then((List<Device> wirelessDevices) async {
      // If device is already chosen, don't update terminal with
      // wireless device list.
      if (chosenDevice != null) {
        return wirelessDevices;
      }

      final List<Device> allDevices = attachedDevices + wirelessDevices;

      if (_logger.isVerbose) {
        await _verbosePrintWirelessDevices(attachedDevices, wirelessDevices);
      } else {
        // Also clear any invalid device selections.
        numLinesToClear += deviceSelection.invalidAttempts;
        await _printWirelessDevices(wirelessDevices, numLinesToClear);
      }
      _logger.printStatus('');

      // Reprint device option list.
      _displayDeviceOptions(allDevices);
      deviceSelection.devices = allDevices;
      // Reprint device option prompt.
      _logger.printStatus(
        '$_chooseOneMessage: ',
        emphasis: true,
        newline: false,
      );
      return wirelessDevices;
    });

    // Used for testing.
    if (waitForWirelessBeforeInput) {
      await futureWirelessDevices;
    }

    // Wait for user to select a device.
    chosenDevice = await futureChosenDevice;

    // Update the [DeviceManager.specifiedDeviceId] so that the user will not
    // be prompted again.
    _deviceManager.specifiedDeviceId = chosenDevice.id;

    return <Device>[chosenDevice];
  }

  /// Reprint list of attached devices before printing list of wireless devices.
  Future<void> _verbosePrintWirelessDevices(
    List<Device> attachedDevices,
    List<Device> wirelessDevices,
  ) async {
    if (wirelessDevices.isEmpty) {
      _logger.printStatus(_noWirelessDevicesFoundMessage);
    }
    // The iOS xcdevice outputs once wireless devices are done loading, so
    // reprint attached devices so they're grouped with the wireless ones.
    _logger.printStatus(_connectedDevicesMessage);
    await Device.printDevices(attachedDevices, _logger);

    if (wirelessDevices.isNotEmpty) {
      _logger.printStatus('');
      _logger.printStatus(_wirelesslyConnectedDevicesMessage);
      await Device.printDevices(wirelessDevices, _logger);
    }
  }

  /// Clear [numLinesToClear] lines from terminal. Print message and list of
  /// wireless devices.
  Future<void> _printWirelessDevices(
    List<Device> wirelessDevices,
    int numLinesToClear,
  ) async {
    _logger.printStatus(
      globals.terminal.clearLines(numLinesToClear),
      newline: false,
    );
    _logger.printStatus('');
    if (wirelessDevices.isEmpty) {
      _logger.printStatus(_noWirelessDevicesFoundMessage);
    } else {
      _logger.printStatus(_wirelesslyConnectedDevicesMessage);
      await Device.printDevices(wirelessDevices, _logger);
    }
  }
}

@visibleForTesting
class TargetDeviceSelection {
  TargetDeviceSelection(this._logger);

  List<Device> devices = <Device>[];
  final Logger _logger;
  int invalidAttempts = 0;

  /// Prompt user to select a device and wait until they select a valid device.
  ///
  /// If the user selects `q`, exit the tool.
  ///
  /// If the user selects an invalid number, reprompt them and continue waiting.
  Future<Device> userSelectDevice() async {
    Device? chosenDevice;
    while (chosenDevice == null) {
      final String userInputString = await readUserInput();
      if (userInputString.toLowerCase() == 'q') {
        throwToolExit('');
      }
      final int deviceIndex = int.parse(userInputString) - 1;
      if (deviceIndex > -1 && deviceIndex < devices.length) {
        chosenDevice = devices[deviceIndex];
      }
    }

    return chosenDevice;
  }

  /// Prompt user to select a device and wait until they select a valid
  /// character.
  ///
  /// Only allow input of a number or `q`.
  @visibleForTesting
  Future<String> readUserInput() async {
    final RegExp pattern = RegExp(r'\d+$|q', caseSensitive: false);
    String? choice;
    globals.terminal.singleCharMode = true;
    while (choice == null || choice.length > 1 || !pattern.hasMatch(choice)) {
      _logger.printStatus(_chooseOneMessage, emphasis: true, newline: false);
      // prompt ends with ': '
      _logger.printStatus(': ', emphasis: true, newline: false);
      choice = (await globals.terminal.keystrokes.first).trim();
      _logger.printStatus(choice);
      invalidAttempts++;
    }
    globals.terminal.singleCharMode = false;
    return choice;
  }
}
