# 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 logging
import os
from enum import Enum
from typing import Callable

import fx_cmd
from async_utils.command import (
    AsyncCommand,
    CommandOutput,
    StderrEvent,
    StdoutEvent,
)

logger = logging.getLogger(__name__)


class FfxOutputFormat(Enum):
    TEXT = 0
    JSON = 1
    PRETTY_JSON = 2


class FfxCmd(fx_cmd.ExecutableCommand):
    def __init__(
        self,
        inner: fx_cmd.ExecutableCommand | None = None,
        output_format: FfxOutputFormat = FfxOutputFormat.TEXT,
    ):
        """Wrapper for executing ffx commands through fx.

        Args:
            inner (ExecutableCommand, optional): Configured command wrapper. If unset, use a default FxCmd.
            output_format (FfxOutputFormat, optional): Output format for ffx. Defaults to FfxOutputFormat.TEXT.
        """
        self._ffx_prefix_args: list[str] = []
        match output_format:
            case FfxOutputFormat.TEXT:
                pass
            case FfxOutputFormat.JSON:
                self._ffx_prefix_args = ["--machine", "json"]
            case FfxOutputFormat.PRETTY_JSON:
                self._ffx_prefix_args = ["--machine", "json-pretty"]
            case _:
                assert False, f"Unknown output format {output_format}"

        if inner is None:
            inner = fx_cmd.FxCmd()
        self._inner: fx_cmd.ExecutableCommand = inner

    @staticmethod
    def create_test_inner(
        path_to_ffx: str,
        *extra_args: str,
    ) -> fx_cmd.ExecutableCommand:
        """Create an ExecutableCommand that calls a specific ffx for tests.

        Args:
            path_to_ffx (str): Path to an ffx binary to execute.
            extra_args (str): Extra arguments to pass to ffx.

        Returns:
            ExecutableCommand: Configured wrapper for use as FfxCmd inner.
        """
        if not os.path.isfile(path_to_ffx):
            raise RuntimeError(
                f"Expected ffx at path {path_to_ffx}, but it is not a file"
            )

        class TestExecutor(fx_cmd.ExecutableCommand):
            async def start(self, *args: str) -> AsyncCommand:
                logger.debug("Processing command line...")
                index_of_ffx = 0
                for i, val in enumerate(args):
                    if val == "ffx":
                        index_of_ffx = i
                        break
                logger.debug(f"Old command line was {args}")
                command_line = (
                    [path_to_ffx]
                    + list(extra_args)
                    + list(args[index_of_ffx + 1 :])
                )
                logger.info(f"Executing ffx for test\n  {command_line}")
                return await AsyncCommand.create(*command_line)

        return TestExecutor()

    def command_line(self, *args: str) -> list[str]:
        """Format a command line with ffx-specific settings.

        Returns:
            list[str]: Formatted command line.
        """
        return ["ffx"] + self._ffx_prefix_args + list(args)

    # overrides base class
    async def start(self, *args: str) -> AsyncCommand:
        return await self._inner.start(*self.command_line(*args))

    # overrides base class
    def sync(
        self,
        *args: str,
        stdout_callback: Callable[[StdoutEvent], None] | None = None,
        stderr_callback: Callable[[StderrEvent], None] | None = None,
    ) -> CommandOutput:
        return self._inner.sync(
            *self.command_line(*args),
            stdout_callback=stdout_callback,
            stderr_callback=stderr_callback,
        )
