# Copyright 2024 The Fuchsia 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 asyncio
import atexit
from collections.abc import Awaitable
import os
import random
import signal
import string
import subprocess
import sys
import tempfile
import typing

from daemon_manager import DaemonManager
from portpicker import portpicker

from event import EventRecorder
import test_list_file


async def _start_zxdb_daemon(
    recorder: EventRecorder | None, port: int
) -> DaemonManager:
    try:
        manager = DaemonManager(port=port, connect_to_existing=True)
        proc = await manager.start()
        if proc is None:
            raise RuntimeError(
                "Daemon process was not started (already running or failed)"
            )
    except Exception as e:
        raise RuntimeError(f"Failed to start zxdb-daemon: {e}") from e

    # Print a hint when using DAP mode for how to connect with zxdb-cli.
    if recorder is not None:
        recorder.emit_info_message(
            "A new fx debug cli session has been started automatically, "
            "get started with `fx debug cli wait-for-event`."
        )

    return manager


def spawn(
    tests: list[test_list_file.Test],
    on_debugger_ready: typing.Callable[[], Awaitable[typing.Any]],
    recorder: EventRecorder | None = None,
    break_on_failure: bool = False,
    enable_debug_adapter: bool = False,
    debug_adapter_port: int | None = None,
    breakpoints: list[str] | None = None,
) -> subprocess.Popen[bytes]:
    """Spawn zxdb in a subprocess.

    Spawn zxdb and attach to |tests|, while waiting for a test failure reported by either
    exception or software breakpoint. Standard output for this program is redirected to a fifo,
    which zxdb will stream to the console. The debugger is spawned in a synchronous process since
    zxdb will be handling all of the stdio streams itself and will take control of forwarding IO
    from python back to the console. The caller has no responsibility to deal with any input or
    output from the spawned process.

    Args:
        tests (list[test_list_file.Test]): List of tests selected to be executed.
        on_debugger_ready (typing.Callable): An async closure to be issued when the debugger is
                                             ready for processes to be spawned.
        recorder (event.EventRecorder | None): Recorder for events. Defaults to None.
        break_on_failure (bool): Whether or not we are in break-on-failure mode.
        enable_debug_adapter (bool): Enables zxdb's DebugAdapter server.
        debug_adapter_port (int | None): Sets the port for the DebugAdapter server. If None, a
                                         random one is assigned.
        breakpoints (list[str]): List of breakpoint locations to install. Note: this may slow down
                                 test execution significantly.

    Returns:
        subprocess.Popen: process handle for the zxdb process group.

        Note: The caller is responsible for killing the process group associated with the returned
        process.
    """
    breakpoints = breakpoints or []
    fifo = os.path.join(
        tempfile.gettempdir()
        + "/zxdbpipe-"
        + "".join(
            random.choice(string.ascii_letters + string.digits)
            for _ in range(6)
        )
    )

    os.mkfifo(fifo)

    attach_args = []
    for test in tests:
        # If there are no explicit breakpoints, then we can weakly attach to all tests. Explicit
        # breakpoints require us to load symbols proactively.
        if not breakpoints:
            attach_args.extend(
                ["--execute", f"attach --weak --recursive {test.name()}"]
            )
        else:
            attach_args.extend(
                ["--execute", f"attach --recursive {test.name()}"]
            )

    # If only --breakpoint was specified on the command line (we won't get here if neither
    # debug option was specified), we want to output a more general message than "test
    # failure". Zxdb will default to filling in the type of exception in this slot if it's
    # unspecified, so we don't need to specify any additional text. If both options are
    # specified, it is impossible to know which one will happen first, so use the more specific
    # text.
    embedded_mode_context_args = []
    if break_on_failure:
        embedded_mode_context_args = ["--embedded-mode-context", "test failure"]

    port: int | None = None
    debug_adapter_args = []

    # |enable_debug_adapter| means we're always going to spawn a zxdb-daemon process now.
    # zxdb-daemon will connect to the zxdb that we create below.
    if enable_debug_adapter:
        port = (
            debug_adapter_port
            if debug_adapter_port is not None
            else portpicker.pick_unused_port()
        )

        debug_adapter_args = ["--enable-debug-adapter"]

        debug_adapter_args.append("--debug-adapter-port")
        debug_adapter_args.append(f"{port}")

    zxdb_args = [
        "fx",
        "ffx",
        "debug",
        "connect",
        "--new-agent",
        "--",
        *attach_args,
        "--console-mode",
        "embedded",
        *embedded_mode_context_args,
        "--stream-file",
        fifo,
        "--signal-when-ready",
        str(os.getpid()),
        *debug_adapter_args,
    ]

    # Add the requested breakpoints.
    for bp in breakpoints:
        zxdb_args += ["--execute", f"break {bp}"]

    # Use os.setpgrp instead of start_new_session=True, because we're going to explicitly handoff
    # control of the foreground terminal to zxdb (and take it back during _cleanup below). Using
    # start_new_session=True would create the process in a separate session, which will raise EPERM
    # if we try to give it our TTY.
    debugger_process = subprocess.Popen(
        args=zxdb_args, preexec_fn=os.setpgrp, stderr=subprocess.STDOUT
    )

    # Give control of the tty to zxdb. This lets zxdb know that it has control of the TTY that we
    # started with.
    #
    # Note that we do NOT need to set this back to our pgrp since our output will be routed through
    # zxdb until the very end. If we try to call tcsetpgrp again during shutdown, we'll race with
    # the shell and could leave a job suspended while waiting on an unnecessary SIGTTOU. This has no
    # effect when running in debug_adapter mode since zxdb will not make use of terminal features in
    # this mode.
    os.tcsetpgrp(sys.stdin.fileno(), debugger_process.pid)

    daemon_manager: DaemonManager | None = None

    async def init_debugger() -> None:
        nonlocal daemon_manager
        try:
            if enable_debug_adapter and port is not None:
                daemon_manager = await _start_zxdb_daemon(recorder, port)
        except Exception as e:
            if recorder is not None:
                recorder.emit_warning_message(
                    f"Failed to start zxdb-daemon: {e}"
                )
        await on_debugger_ready()

    def on_sigusr1() -> None:
        # Remove the signal handler immediately so it doesn't fire again.
        loop.remove_signal_handler(signal.SIGUSR1)

        asyncio.create_task(init_debugger())

        # Replace stdout with the named pipe we created and enable line buffering.
        # Note: 1 == line buffered. See https://docs.python.org/3/library/functions.html#open.
        sys.stdout = open(fifo, "w", buffering=1)

    # zxdb will send us a SIGUSR1 when it has successfully connected to DebugAgent and is ready to
    # stream output.
    loop = asyncio.get_event_loop()
    loop.add_signal_handler(signal.SIGUSR1, on_sigusr1)

    def _cleanup() -> None:
        # Close stdout. This may have already been done at the end of all the tests in main.py, but
        # we do it again here to catch the ctrl+c case and still try to cleanly restore the terminal
        # and clean up the socket to DebugAgent.
        sys.stdout.close()
        sys.stdout = open(os.devnull, "w")

        try:
            os.remove(fifo)
        except FileNotFoundError:
            # The tests for this don't actually create a file for the fifo, and we don't want to
            # throw an exception, since we were trying to remove the file anyway.
            pass

        # Clean up daemon process if it was running
        if daemon_manager is not None:
            try:
                daemon_manager.stop_sync(timeout=5.0)
            except BaseException:
                pass

        try:
            # Give zxdb a chance to gracefully shutdown, in the normal case this should return
            # immediately, but when handling ctrl+c in embedded mode we wait some time to run
            # cleanup routines.
            debugger_process.wait(5)
        except subprocess.TimeoutExpired as e:
            sys.stderr.write(f"{e}\n")
            sys.stderr.flush()
        finally:
            # zxdb should have gracefully exited by now, if it hasn't forcefully terminate and
            # inform the user that they may need to reset their terminal.
            if debugger_process.poll() is None:
                sys.stderr.write(
                    "⚠️  Warning: zxdb did not exit normally. `reset` will fix your terminal ⚠️\n"
                )
                sys.stderr.flush()
                debugger_process.terminate()

    atexit.register(_cleanup)

    return debugger_process
