"""Wrapper around `xcrun simctl`."""

import os
from typing import List, Optional, Union
import shlex
import subprocess

from isim.device import Device, DeviceNotFoundError
from isim.device_pair import DevicePair
from isim.device_type import DeviceType, DeviceTypeNotFoundError
from isim.runtime import Runtime, RuntimeNotFoundError

# Advanced:

#	pbsync              Sync the pasteboard content from one pasteboard to another.
#	pbcopy              Copy standard input onto the device pasteboard.
#	pbpaste             Print the contents of the device's pasteboard to standard output.
#	io                  Set up a device IO operation.
#	spawn               Spawn a process on a device.
#	launch              Launch an application by identifier on a device.


# DONE:

#	addmedia            Add photos, live photos, or videos to the photo library of a device
#	boot                Boot a device.
#	clone               Clone an existing device.
#	create              Create a new device.
#	delete              Delete a device or all unavailable devices.
#	erase               Erase a device's contents and settings.
#	get_app_container   Print the path of the installed app's container
#	getenv              Print an environment variable from a running device.
#	icloud_sync         Trigger iCloud sync on a device.
#	install             Install an app on a device.
#	list                List available devices, device types, runtimes, or device pairs.
#	logverbose          enable or disable verbose logging for a device
#	openurl             Open a URL in a device.
#	pair                Create a new watch and phone pair.
#	pair_activate       Set a given pair as active.
#	rename              Rename a device.
#	shutdown            Shutdown a device.
#	terminate           Terminate an application by identifier on a device.
#	uninstall           Uninstall an app from a device.
#	unpair              Unpair a watch and phone pair.
#	upgrade             Upgrade a device to a newer runtime.



# Won't Do:

#	help                Prints the usage for a given subcommand.


def diagnose(
        *,
        output_path: str,
        all_logs: bool = False,
        include_data_directory: bool = False,
        archive: bool = True,
        timeout: int = 300,
        udids: Optional[Union[List[str], str]] = None
    ) -> str:
    """Run the xcrun simctl diagnose command.

    By default, this will run only for booted devices. Set all_logs to True to
    gather data for non-booted devices.

    To include the data directory, set include_data_directory to True.

    If udid is set, it will only connect diagnostics from that device. However,
    if all_logs is set, that will override this setting.

    Returns the location of the archive.
    """

    output_archive = f'{output_path}.tar.gz'

    if os.path.exists(output_path):
        raise FileExistsError('The output directory already exists')

    if os.path.exists(output_archive):
        raise FileExistsError(f'The output archive file already exists: "{output_archive}"')

    # I'm not entirely sure what the '-l' flag does. It's not documented, but if
    # I don't set it, the command just waits forever without doing anything.
    # LinkedIn use this flag for their Bluepill tool.
    full_command = ['xcrun', 'simctl', 'diagnose', '-l', '-b', f'--timeout={timeout}', f'--output={shlex.quote(output_path)}']

    if not archive:
        full_command.append('--no-archive')

    if include_data_directory:
        full_command.append('--data-container')

    if all_logs:
        full_command.append('--all-logs')

    if udids is not None:
        if isinstance(udids, str):
            full_command.append(f'--udid={udids}')
        else:
            full_command += [f'--udid={udid}' for udid in udids]

    command_string = " ".join(full_command)

    # Let the exception bubble up
    _ = subprocess.run(
        command_string,
        universal_newlines=True,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        check=True
    )

    return output_archive
