# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import annotations

import shlex
from typing import TYPE_CHECKING, Dict, Iterable

from crossbench import plt
from crossbench.browsers.attributes import BrowserAttributes
from crossbench.parse import PathParser
from crossbench.probes.probe import (Probe, ProbeConfigParser, ProbeContext,
                                     ProbeKeyT, ProbeValidationError)
from crossbench.probes.result_location import ResultLocation
from crossbench.probes.results import EmptyProbeResult, ProbeResult

if TYPE_CHECKING:
  from crossbench.browsers.browser import Browser
  from crossbench.env import HostEnvironment
  from crossbench.path import LocalPath
  from crossbench.runner.run import Run

_DEBUGGER_LOOKUP: Dict[str, str] = {
    "macos": "lldb",
    "linux": "gdb",
}

DEFAULT_GEOMETRY = "80x70"


class DebuggerProbe(Probe):
  """
  Probe debugging chrome's renderer process.
  """
  NAME = "debugger"
  RESULT_LOCATION = ResultLocation.BROWSER
  IS_GENERAL_PURPOSE = True

  @classmethod
  def config_parser(cls) -> ProbeConfigParser:
    parser = super().config_parser()
    parser.add_argument(
        "debugger",
        type=PathParser.binary_path,
        default=_DEBUGGER_LOOKUP.get(plt.PLATFORM.name,
                                     "debugger probe not supported"),
        help="Set a custom debugger binary. "
        "Currently only gdb and lldb are supported.")
    parser.add_argument(
        "auto_run",
        type=bool,
        default=True,
        help="Automatically start the renderer process in the debugger.")
    parser.add_argument(
        "spare_renderer_process",
        type=bool,
        default=False,
        help=("Chrome-only: Enable/Disable spare renderer processes via \n"
              "--enable-/--disable-features=SpareRendererForSitePerProcess.\n"
              "Spare renderers are disabled by default when profiling "
              "for fewer uninteresting processes."))
    parser.add_argument(
        "geometry",
        type=str,
        default=DEFAULT_GEOMETRY,
        help="Geometry of the terminal (xterm) used to display the debugger.")
    parser.add_argument(
        "args",
        type=str,
        default=tuple(),
        is_list=True,
        help="Additional args that are passed to the debugger.")
    return parser

  def __init__(
      self,
      debugger: LocalPath,
      auto_run: bool = True,
      spare_renderer_process: bool = False,
      geometry: str = DEFAULT_GEOMETRY,
      args: Iterable[str] = ()) -> None:
    super().__init__()
    self._debugger_bin = debugger
    self._debugger_args = args
    self._auto_run = auto_run
    self._geometry = geometry
    self._spare_renderer_process = spare_renderer_process

  @property
  def key(self) -> ProbeKeyT:
    return super().key + (
        ("debugger", str(self._debugger_bin)),
        ("debugger_args", tuple(self._debugger_args)),
        ("auto_run", self._auto_run),
        ("geometry", str(self._geometry)),
        ("spare_renderer_process", self._spare_renderer_process),
    )

  def validate_browser(self, env: HostEnvironment, browser: Browser) -> None:
    super().validate_browser(env, browser)
    self.expect_browser(browser, BrowserAttributes.CHROMIUM_BASED)
    # TODO: support more platforms
    if not (browser.platform.is_macos or browser.platform.is_linux):
      raise ValueError(f"Only supported on linux and macOS, but got {browser}")
    if browser.platform.is_remote:
      raise ProbeValidationError(self, "Does not run on remote platforms.")
    # TODO: support more terminals.
    if not browser.platform.which("xterm"):
      raise ProbeValidationError(self, "Please install xterm on your system.")

  def attach(self, browser: Browser) -> None:
    super().attach(browser)
    assert browser.attributes.is_chromium_based
    flags = browser.flags
    flags.set("--no-sandbox")
    flags.set("--disable-hang-monitor")
    flags["--renderer-cmd-prefix"] = self.renderer_cmd_prefix()
    if not self._spare_renderer_process:
      browser.features.disable("SpareRendererForSitePerProcess")

  def renderer_cmd_prefix(self) -> str:
    # TODO: support more terminals.
    debugger_cmd = [
        "xterm",
        "-title",
        "renderer",
        "-geometry",
        self._geometry,
        "-e",
        str(self._debugger_bin),
    ]
    if self._debugger_bin.name == "lldb":
      if self._auto_run:
        debugger_cmd += ["-o", "run"]
      if self._debugger_args:
        debugger_cmd.extend(self._debugger_args)
      debugger_cmd += ["--"]
    else:
      assert self._debugger_bin.name == "gdb", (
          f"Unsupported debugger: {self._debugger_bin}")
      if self._auto_run:
        debugger_cmd += ["-ex", "run"]
      if self._debugger_args:
        debugger_cmd.extend(self._debugger_args)
      debugger_cmd += ["--args"]
    return shlex.join(debugger_cmd)

  def get_context(self, run: Run) -> DebuggerContext:
    return DebuggerContext(self, run)


class DebuggerContext(ProbeContext[DebuggerProbe]):

  def start(self) -> None:
    pass

  def stop(self) -> None:
    pass

  def teardown(self) -> ProbeResult:
    return EmptyProbeResult()
