# Copyright 2020 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""API for Bazel calls for config, cquery, and required fragment info.

There's no Python Bazel API so we invoke Bazel as a subprocess.
"""
import json
import os
import subprocess
from typing import Callable
from typing import List
from typing import Tuple
# Do not edit this line. Copybara replaces it with PY2 migration helper.
from frozendict import frozendict
from tools.ctexplain.types import Configuration
from tools.ctexplain.types import ConfiguredTarget
from tools.ctexplain.types import HostConfiguration
from tools.ctexplain.types import NullConfiguration


def run_bazel_in_client(args: List[str]) -> Tuple[int, List[str], List[str]]:
  """Calls bazel within the current workspace.

  For production use. Tests use an alternative invoker that goes through test
  infrastructure.

  Args:
    args: the arguments to call Bazel with

  Returns:
    Tuple of (return code, stdout, stderr)
  """
  result = subprocess.run(
      ["blaze"] + args,
      cwd=os.getcwd(),
      stdout=subprocess.PIPE,
      stderr=subprocess.PIPE,
      check=False)
  return (result.returncode, result.stdout.decode("utf-8").split(os.linesep),
          result.stderr)


class BazelApi():
  """API that accepts injectable Bazel invocation logic."""

  def __init__(self,
               run_bazel: Callable[[List[str]],
                                   Tuple[int, List[str],
                                         List[str]]] = run_bazel_in_client):
    self.run_bazel = run_bazel

  def cquery(self,
             args: List[str]) -> Tuple[bool, str, Tuple[ConfiguredTarget, ...]]:
    """Calls cquery with the given arguments.

    Args:
      args: A list of cquery command-line arguments, one argument per entry.

    Returns:
      (success, stderr, cts), where success is True iff the query succeeded,
      stderr contains the query's stderr (regardless of success value), and cts
      is the configured targets found by the query if successful, empty
      otherwise.

      ct order preserves cquery's output order. This is topologically sorted
      with duplicates removed. So no unique configured target appears twice and
      if A depends on B, A appears before B.
    """
    base_args = ["cquery", "--show_config_fragments=transitive"]
    (returncode, stdout, stderr) = self.run_bazel(base_args + args)
    if returncode != 0:
      return (False, stderr, ())

    cts = []
    for line in stdout:
      if not line.strip():
        continue
      ctinfo = _parse_cquery_result_line(line)
      if ctinfo is not None:
        cts.append(ctinfo)

    return (True, stderr, tuple(cts))

  def get_config(self, config_hash: str) -> Configuration:
    """Calls "bazel config" with the given config hash.

    Args:
      config_hash: A config hash as reported by "bazel cquery".

    Returns:
      The matching configuration or None if no match is found.

    Raises:
      ValueError: On any parsing problems.
    """
    if config_hash == "HOST":
      return HostConfiguration()
    elif config_hash == "null":
      return NullConfiguration()

    base_args = ["config", "--output=json"]
    (returncode, stdout, stderr) = self.run_bazel(base_args + [config_hash])
    if returncode != 0:
      raise ValueError("Could not get config: " + stderr)
    config_json = json.loads(os.linesep.join(stdout))
    fragments = frozendict({
        _base_name(entry["name"]):
        tuple(_base_name(clazz) for clazz in entry["fragmentOptions"])
        for entry in config_json["fragments"]
    })
    options = frozendict({
        _base_name(entry["name"]): frozendict(entry["options"])
        for entry in config_json["fragmentOptions"]
    })
    return Configuration(fragments, options)


# TODO(gregce): have cquery --output=jsonproto support --show_config_fragments
# so we can replace all this regex parsing with JSON reads.
def _parse_cquery_result_line(line: str) -> ConfiguredTarget:
  """Converts a cquery output line to a ConfiguredTarget.

  Expected input is:

      "<label> (<config hash>) [configFragment1, configFragment2, ...]"

  or:
      "<label> (null)"

  Args:
    line: The expected input.

  Returns:
    Corresponding ConfiguredTarget if the line matches else None.
  """
  tokens = line.split(maxsplit=2)
  label = tokens[0]
  if tokens[1][0] != "(" or tokens[1][-1] != ")":
    raise ValueError(f"{tokens[1]} in {line} not surrounded by parentheses")
  config_hash = tokens[1][1:-1]
  if config_hash == "null":
    fragments = ()
  else:
    if tokens[2][0] != "[" or tokens[2][-1] != "]":
      raise ValueError(f"{tokens[2]} in {line} not surrounded by [] brackets")
    # The fragments list looks like '[Fragment1, Fragment2, ...]'. Split the
    # whole line on ' [' to get just this list, then remove the final ']', then
    # split again on ', ' to convert it to a structured tuple.
    fragments = tuple(line.split(" [")[1][0:-1].split(", "))
  return ConfiguredTarget(
      label=label,
      config=None,  # Not yet available: we'll need `bazel config` to get this.
      config_hash=config_hash,
      transitive_fragments=fragments)


def _base_name(full_name: str) -> str:
  """Strips a fully qualified Java class name to the file scope.

  Examples:
    - "A.B.OuterClass" -> "OuterClass"
    - "A.B.OuterClass$InnerClass" -> "OuterClass$InnerClass"

  Args:
    full_name: Fully qualified class name.

  Returns:
    Stripped name.
  """
  return full_name.split(".")[-1]
