# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.

"""This script helps to invoke gn and ninja
which lie in depot_tools repository."""

import json
import os
import re
import shutil
import subprocess
import sys
import tempfile


def FindSrcDirPath():
  """Returns the abs path to the src/ dir of the project."""
  src_dir = os.path.dirname(os.path.abspath(__file__))
  while os.path.basename(src_dir) != 'src':
    src_dir = os.path.normpath(os.path.join(src_dir, os.pardir))
  return src_dir


SRC_DIR = FindSrcDirPath()
sys.path.append(os.path.join(SRC_DIR, 'build'))
import find_depot_tools


def RunGnCommand(args, root_dir=None):
  """Runs `gn` with provided args and return error if any."""
  try:
    command = [
      sys.executable,
      os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py')
    ] + args
    subprocess.check_output(command, cwd=root_dir)
  except subprocess.CalledProcessError as err:
    return err.output
  return None


# GN_ERROR_RE matches the summary of an error output by `gn check`.
# Matches "ERROR" and following lines until it sees an empty line or a line
# containing just underscores.
GN_ERROR_RE = re.compile(r'^ERROR .+(?:\n.*[^_\n].*$)+', re.MULTILINE)


def RunGnCheck(root_dir=None):
  """Runs `gn gen --check` with default args to detect mismatches between
  #includes and dependencies in the BUILD.gn files, as well as general build
  errors.

  Returns a list of error summary strings.
  """
  out_dir = tempfile.mkdtemp('gn')
  try:
    error = RunGnCommand(['gen', '--check', out_dir], root_dir)
  finally:
    shutil.rmtree(out_dir, ignore_errors=True)
  return GN_ERROR_RE.findall(error) if error else []


def RunNinjaCommand(args, root_dir=None):
  """Runs ninja quietly. Any failure (e.g. clang not found) is
     silently discarded, since this is unlikely an error in submitted CL."""
  command = [
              os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'ninja')
            ] + args
  p = subprocess.Popen(command, cwd=root_dir,
                       stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  out, _ = p.communicate()
  return out


def GetClangTidyPath():
  """POC/WIP! Use the one we have, even it doesn't match clang's version."""
  tidy = ('third_party/android_ndk/toolchains/'
          'llvm/prebuilt/linux-x86_64/bin/clang-tidy')
  return os.path.join(SRC_DIR, tidy)


def GetCompilationDb(root_dir=None):
  """Run ninja compdb tool to get proper flags, defines and include paths."""
  # The compdb tool expect a rule.
  commands = json.loads(RunNinjaCommand(['-t', 'compdb', 'cxx'], root_dir))
  # Turns 'file' field into a key.
  return {v['file']: v for v in commands}


def GetCompilationCommand(filepath, gn_args, work_dir):
  """Get the whole command used to compile one cc file.
  Typically, clang++ with flags, defines and include paths.

  Args:
      filepath: path to .cc file.
      gen_args: build configuration for gn.
      work_dir: build dir.

  Returns:
    Command as a list, ready to be consumed by subprocess.Popen.
  """
  gn_errors = RunGnCommand(['gen'] + gn_args + [work_dir])
  if gn_errors:
    raise(RuntimeError(
      'FYI, cannot complete check due to gn error:\n%s\n'
      'Please open a bug.' % gn_errors))

  # Needed for single file compilation.
  commands = GetCompilationDb(work_dir)

  # Path as referenced by ninja.
  rel_path = os.path.relpath(os.path.abspath(filepath), work_dir)

  # Gather defines, include path and flags (such as -std=c++11).
  try:
    compilation_entry = commands[rel_path]
  except KeyError:
    raise ValueError('%s: Not found in compilation database.\n'
                     'Please check the path.' % filepath)
  command = compilation_entry['command'].split()

  # Remove troublesome flags. May trigger an error otherwise.
  if '-MMD' in command:
    command.remove('-MMD')
  if '-MF' in command:
    index = command.index('-MF')
    del command[index:index+2]  # Remove filename as well.

  return command
