# Copyright 2018 The Chromium 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 re

from recipe_engine import recipe_api

from . import constants

class GnApi(recipe_api.RecipeApi):

  _DEFAULT_STEP_NAME = 'read GN args'
  _ARG_RE = re.compile('\s*(\w+)\s*=')
  _NON_LOCAL_ARGS = frozenset(['goma_dir', 'target_sysroot'])
  _DEFAULT_MAX_TEXT_LINES = 15

  DEFAULT = constants.DEFAULT
  TEXT = constants.TEXT
  LOGS = constants.LOGS

  def read_args(self, build_dir, step_name=None):
    """Read the GN args.

    Args:
      build_dir: The Path to the build output directory. The args.gn file will
        be extracted from this location. The args.gn file must already exist (gn
        or mb should have already been run before calling this method).

    Returns:
      A tuple containing the contents of the args.gn file as a single string and
      the step result of reading the file.
    """
    args_file_path = build_dir.join('args.gn')
    step_name = step_name or self._DEFAULT_STEP_NAME
    fake_args = (
        'goma_dir = "/b/build/slave/cache/goma_client"\n'
        'target_cpu = "x86"\n'
        'use_goma = true\n')
    args = self.m.file.read_text(step_name, args_file_path, fake_args)
    return args, self.m.step.active_result

  def reformat_args(self, args):
    """Reformat the GN args to be more useful for local repros.

    Some of the arguments have values that are specific to individual runs and
    so a developer would likely not want to copy them to their own checkout when
    attempting to reproduce an issue locally. To enable ease of use, these
    arguments are moved to the end of the arguments so that a single contiguous
    region can be copied in order to create a build directory with the
    appropriate arguments.

    Args:
      args: A string containing the args.gn content to reformat.

    Returns:
      The reformatted args.gn content as a single string.
    """
    local_lines = []
    non_local_lines = []
    for l in args.splitlines():
      match = self._ARG_RE.match(l)
      if match is not None and match.group(1) in self._NON_LOCAL_ARGS:
        non_local_lines.append(l)
      else:
        local_lines.append(l)
    return '\n'.join(local_lines + non_local_lines)

  def present_args(self, result, args, location=None, max_text_lines=None):
    """Present the GN args.

    Args:
      result: The step result to present the GN args on.
      args: A string containing the args.gn content to present.
      location: Controls where the GN args for the build should be presented. By
        default or if gn.DEFAULT, the args will be in step_text if the count of
        lines is less than max_text_lines or the logs otherwise. To force the
        presentation to the step_text or logs, use gn.TEXT or gn.LOGS,
        respectively.
      max_text_lines: The maximum number of lines of GN args to display in the
        step_text when using the default behavior for displaying GN args.
    """
    location = location or self.DEFAULT
    assert location in (self.DEFAULT, self.TEXT, self.LOGS), \
        "location must be one of gn.DEFAULT, gn.TEXT or gn.LOGS"

    lines = args.splitlines()

    if location == self.DEFAULT:
      if max_text_lines is None:
        max_text_lines = self._DEFAULT_MAX_TEXT_LINES
      if len(lines) > max_text_lines:
        result.presentation.step_text += (
            '<br/>Count of GN args (%d) exceeds limit (%d),'
            ' presented in logs instead') % (len(lines), max_text_lines)
        location = self.LOGS

    if location == self.LOGS:
      result.presentation.logs['gn_args'] = lines
    else:
      result.presentation.step_text += '<br/>'.join([''] + lines)

  def get_args(self, build_dir, location=None, max_text_lines=None,
               step_name=None):
    """Get the GN args for the build.

    A step will be executed that fetches the args.gn file and adds the contents
    to the presentation for the step.

    Args:
      build_dir: The Path to the build output directory. The args.gn file will
        be extracted from this location. The args.gn file must already exist (gn
        or mb should have already been run before calling this method).
      location: Controls where the GN args for the build should be presented. By
        default or if gn.DEFAULT, the args will be in step_text if the count of
        lines is less than max_text_lines or the logs otherwise. To force the
        presentation to the step_text or logs, use gn.TEXT or gn.LOGS,
        respectively.
      max_text_lines: The maximum number of lines of GN args to display in the
        step_text when using the default behavior for displaying GN args.
      step_name: The name of the step for reading the args.

    Returns:
      The content of the args.gn file.
    """
    args, result = self.read_args(build_dir, step_name=step_name)
    reformatted_args = self.reformat_args(args)
    self.present_args(result, reformatted_args,
                      location=location, max_text_lines=max_text_lines)
    return args

  def _gn_cmd(self, name, cmd, gn_path=None, log_name='gn output'):
    if not gn_path:
      gn_path = self.m.depot_tools.gn_py_path
    return self.m.python(
        name, gn_path, cmd, stdout=self.m.raw_io.output_text(name=log_name,
            add_output_log=True))

  def refs(self, build_dir, inputs, all_deps=True, output_type=None,
           output_format='label', step_name='calculate gn refs'):
    """Find reverse dependencies for a given set of inputs.

    See https://gn.googlesource.com/gn/+/master/docs/reference.md#refs for
    more documentation of the command.

    Args:
      build_dir: Path to build output directory.
      inputs: List of label or files to find dependencies of.
      all_deps: Boolean indicating wether or not to include indirect
        dependencies.
      output_type: Type of target (eg: "executable", "shared_library", etc.) to
        restrict outputs to. If None (default), no filtering is preformed.
      output_format: How to display targets. See GN docs for valid options.
        Default is "label".
      step_name: Optional recipe step name to give to the "gn refs" command.
    Returns:
      The set of dependencies found.
    """
    assert isinstance(inputs, list), \
        'Inputs to GN-refs must be a list of files or labels.'
    cmd = [
        'refs',
        '-q',  # Don't print a warning when no refs are found.
        '--as=%s' % output_format,
    ]
    if all_deps:
      cmd += ['--all']
    if output_type:
      cmd += ['--type=%s' % output_type]
    cmd.append(build_dir)
    cmd.extend(inputs)
    step_result = self._gn_cmd(step_name, cmd, log_name='refs')
    return set(step_result.stdout.splitlines())

  def ls(self, build_dir, inputs, output_type=None, output_format='label',
         step_name='list gn targets'):
    """List targets for a given set of inputs.

    See https://gn.googlesource.com/gn/+/master/docs/reference.md#ls for
    more documentation of the command.

    Args:
      build_dir: Path to build output directory.
      inputs: List of patterns to find matching targets for.
      output_type: Type of target (eg: "executable", "shared_library", etc.) to
        restrict outputs to. If None (default), no filtering is preformed.
      output_format: How to display targets. See GN docs for valid options.
        Default is "label".
      step_name: Optional recipe step name to give to the "gn ls" command.
    Returns:
      The set of targets found.
    """
    assert isinstance(inputs, list), \
        'Inputs to GN-ls must be a list of file or label patterns.'
    cmd = [
        'ls',
        '--as=%s' % output_format,
    ]
    if output_type:
      cmd += ['--type=%s' % output_type]
    cmd.append(build_dir)
    cmd.extend(inputs)
    step_result = self._gn_cmd(step_name, cmd, log_name='targets')
    return set(step_result.stdout.splitlines())
