18d307f52SEvan Baconimport chalk from 'chalk';
28d307f52SEvan Bacon
38d307f52SEvan Baconimport { getBestSimulatorAsync } from './getBestSimulator';
48d307f52SEvan Baconimport { Device } from './simctl';
5*8a424bebSJames Ideimport { createSelectionFilter, promptAsync } from '../../../utils/prompts';
68d307f52SEvan Bacon
78d307f52SEvan Bacon/**
88d307f52SEvan Bacon * Sort the devices so the last simulator that was opened (user's default) is the first suggested.
98d307f52SEvan Bacon *
108d307f52SEvan Bacon * @param devices list of devices to sort.
118d307f52SEvan Bacon * @param osType optional sort by operating system.
128d307f52SEvan Bacon */
138d307f52SEvan Baconexport async function sortDefaultDeviceToBeginningAsync(
148d307f52SEvan Bacon  devices: Device[],
158d307f52SEvan Bacon  osType?: Device['osType']
168d307f52SEvan Bacon): Promise<Device[]> {
178d307f52SEvan Bacon  const defaultId = await getBestSimulatorAsync({ osType });
188d307f52SEvan Bacon  if (defaultId) {
198d307f52SEvan Bacon    let iterations = 0;
208d307f52SEvan Bacon    while (devices[0].udid !== defaultId && iterations < devices.length) {
218d307f52SEvan Bacon      devices.push(devices.shift()!);
228d307f52SEvan Bacon      iterations++;
238d307f52SEvan Bacon    }
248d307f52SEvan Bacon  }
258d307f52SEvan Bacon  return devices;
268d307f52SEvan Bacon}
278d307f52SEvan Bacon
288d307f52SEvan Bacon/** Prompt the user to select an Apple device, sorting the most likely option to the beginning. */
298d307f52SEvan Baconexport async function promptAppleDeviceAsync(
308d307f52SEvan Bacon  devices: Device[],
318d307f52SEvan Bacon  osType?: Device['osType']
328d307f52SEvan Bacon): Promise<Device> {
338d307f52SEvan Bacon  devices = await sortDefaultDeviceToBeginningAsync(devices, osType);
348d307f52SEvan Bacon  const results = await promptAppleDeviceInternalAsync(devices);
358d307f52SEvan Bacon  return devices.find(({ udid }) => results === udid)!;
368d307f52SEvan Bacon}
378d307f52SEvan Bacon
388d307f52SEvan Baconasync function promptAppleDeviceInternalAsync(devices: Device[]): Promise<string> {
398d307f52SEvan Bacon  // TODO: provide an option to add or download more simulators
408d307f52SEvan Bacon  // TODO: Add support for physical devices too.
418d307f52SEvan Bacon
428d307f52SEvan Bacon  const { value } = await promptAsync({
438d307f52SEvan Bacon    type: 'autocomplete',
448d307f52SEvan Bacon    name: 'value',
458d307f52SEvan Bacon    limit: 11,
468d307f52SEvan Bacon    message: 'Select a simulator',
478d307f52SEvan Bacon    choices: devices.map((item) => {
488d307f52SEvan Bacon      const isActive = item.state === 'Booted';
498d307f52SEvan Bacon      const format = isActive ? chalk.bold : (text: string) => text;
508d307f52SEvan Bacon      return {
518d307f52SEvan Bacon        title: `${format(item.name)} ${chalk.dim(`(${item.osVersion})`)}`,
528d307f52SEvan Bacon        value: item.udid,
538d307f52SEvan Bacon      };
548d307f52SEvan Bacon    }),
5586ab6f9aSEvan Bacon    suggest: createSelectionFilter(),
568d307f52SEvan Bacon  });
578d307f52SEvan Bacon
588d307f52SEvan Bacon  return value;
598d307f52SEvan Bacon}
60