#!/usr/bin/env python3
# Copyright 2025 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""The stable API endpoint for ChromiumIDE Java language support.

ChromiumIDE executes this script to query information and perform operations.
This script is not meant to be run manually.
"""

import argparse
import concurrent.futures
import dataclasses
import logging
import json
import os
import re
import shlex
import shutil
import subprocess
import sys
from typing import Iterator, List, Optional, Set, Tuple

_SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))

sys.path.append(os.path.join(_SRC_ROOT, 'build'))
import gn_helpers

sys.path.append(os.path.join(_SRC_ROOT, 'build', 'android', 'gyp'))
from util import build_utils

_DEPOT_TOOLS_PATH = os.path.join(_SRC_ROOT, 'third_party', 'depot_tools')

# The API version of the script.
_API_VERSION = 1

# Matches with the package declaration in a Java source file.
_PACKAGE_PATTERN = re.compile(r'package\s+([A-Za-z0-9._]*)\s*;')


@dataclasses.dataclass(frozen=True)
class BuildInfo:
  """Defines the output schema of build-info subcommand."""
  # Directory paths containing Java source files, relative from the src
  # directory.
  source_paths: List[str]

  # JAR file paths, relative from the src directory.
  class_paths: List[str]

  def to_dict(self) -> dict:
    """Converts the BuildInfo object to a dictionary for JSON serialization."""
    return {'sourcePaths': self.source_paths, 'classPaths': self.class_paths}


def _gn_gen(output_dir: str) -> None:
  """Runs 'gn gen' to generate build files for the specified output directory.

  Args:
    output_dir: The path to the build output directory.
  """
  cmd = [
      sys.executable,
      os.path.join(_DEPOT_TOOLS_PATH, 'gn.py'), 'gen', output_dir
  ]
  logging.info('Running: %s', shlex.join(cmd))
  subprocess.check_call(cmd, stdout=sys.stderr)


def _compile(output_dir: str, args: List[str]) -> None:
  """Compiles the specified targets using the build system.

  Args:
    output_dir: The path to the build output directory.
    args: A list of build targets or arguments to pass to the build command.
  """
  cmd = gn_helpers.CreateBuildCommand(output_dir) + args
  logging.info('Running: %s', shlex.join(cmd))
  subprocess.check_call(cmd, stdout=sys.stderr)


def _is_useful_source_jar(source_jar_path: str, output_dir: str) -> bool:
  """Determines if a source JAR is useful for IDE indexing.

  This function filters out certain types of source JARs that are not
  beneficial or could cause issues for IDEs.

  Args:
    source_jar_path: The path to the source JAR file.
    output_dir: The path to the build output directory.

  Returns:
    True if the source JAR should be included, False otherwise.
  """
  # JNI placeholder srcjars contain random stubs.
  if source_jar_path.endswith('_placeholder.srcjar'):
    return False

  # When building a java_library target (e.g. //chrome/android:chrome_java),
  # a srcjar containing relevant resource definitions are generated first (e.g.
  # gen/chrome/android/chrome_java__assetres.srcjar), and it's included in the
  # source path when building the java_library target. This is how R references
  # are resolved when *.java are compiled with javac.
  #
  # When multiple java libraries are linked into an APK (e.g.
  # //clank/java:chrome_apk), another srcjar containing all relevant resource
  # definitions is generated (e.g.
  # gen/clank/java/chrome_apk__compile_resources.srcjar). Note that
  # *__assetres.srcjar used on compiling java libraries are NOT linked to final
  # APKs. This is how R definitions looked up in the run time are linked to an
  # APK.
  #
  # Then let's talk about IDE's business. We cannot add *__assetres.srcjar to
  # the source path of the language server because many of those srcjars
  # contain identically named R classes (e.g. org.chromium.chrome.R) with
  # different sets of resource names. (Note that we don't explicitly exclude
  # them here, but actually they don't appear in *.params.json at all.)
  # Therefore we want to pick a single resource jar that covers all resource
  # definitions in the whole Chromium tree and add it to the source path. An
  # approximation used here is to pick the __compile_resources.srcjar for the
  # main browser binary. This is not perfect though, because there can be some
  # resources not linked into the main browser binary. Ideally we should
  # introduce a GN target producing a resource jar covering all resources
  # across the repository.
  if source_jar_path.endswith('__compile_resources.srcjar'):
    if os.path.exists(os.path.join(_SRC_ROOT, 'clank')):
      private_resources_jar_path = os.path.join(
          output_dir, 'gen/clank/java/chrome_apk__compile_resources.srcjar')
      return source_jar_path == private_resources_jar_path

    public_resources_jar_path = os.path.join(
        output_dir,
        'gen/chrome/android/chrome_public_apk__compile_resources.srcjar')
    return source_jar_path == public_resources_jar_path

  return True


def _find_source_root(source_file: str) -> Optional[str]:
  """Finds the root directory for a given source file based on its package.

  For example, if a file '/path/to/src/org/chromium/foo/Bar.java' declares
  'package org.chromium.foo;', this function will return '/path/to/src'.

  Args:
    source_file: The path to the Java source file.

  Returns:
    The path to the source root, or None if the package declaration cannot be
    found or parsed.
  """
  with open(source_file) as f:
    for line in f:
      if match := _PACKAGE_PATTERN.match(line):
        package_name = match.group(1)
        break
    else:
      return None

  depth = package_name.count('.') + 1
  source_root = source_file.rsplit('/', depth + 1)[0]
  return source_root


def _process_sources(source_files: List[str], output_dir: str,
                     source_path_set: Set[str]) -> None:
  """Processes a list of source files to find their source roots.

  Args:
    source_files: A list of source file paths, relative to the output directory.
    output_dir: The path to the build output directory.
    source_path_set: A set to which identified source root paths will be added.
  """
  processed_dir_set = set()
  for source_file in source_files:
    if not source_file.endswith('.java') or not source_file.startswith('../'):
      continue

    source_file = os.path.normpath(os.path.join(output_dir, source_file))
    source_dir = os.path.dirname(source_file)

    if source_dir in processed_dir_set:
      continue
    processed_dir_set.add(source_dir)

    if source_root := _find_source_root(source_file):
      source_path_set.add(source_root)


def _process_params(params_path: str, output_dir: str,
                    source_path_set: Set[str], class_path_set: Set[str],
                    source_jar_set: Set[str]) -> None:
  """Processes a .params.json file to extract build information.

  .params.json files are generated on `gn gen` and contain metadata about build
  targets, including sources, dependencies, and generated JARs.

  Args:
    params_path: The path to the .params.json file.
    output_dir: The path to the build output directory.
    source_path_set: A set to which identified source root paths will be added.
    class_path_set: A set to which identified classpath JAR paths will be added.
    source_jar_set: A set to which identified source JAR paths will be added.
  """
  with open(params_path) as f:
    params = json.load(f)

  if target_sources_file := params.get('target_sources_file'):
    # If the target is built from source files, add their source roots.
    _process_sources(
        build_utils.ReadSourcesList(
            os.path.join(output_dir, target_sources_file)), output_dir,
        source_path_set)
  elif unprocessed_jar_path := params.get('unprocessed_jar_path'):
    # If is_prebuilt is not set, we guess it from the jar path. The path is
    # relative to outDir, so it starts with ../ if it points to a prebuilt
    # jar in the chrome source tree.
    if params.get('is_prebuilt') or unprocessed_jar_path.startswith('../'):
      # This is a prebuilt jar file. Add it to the class path.
      class_path_set.add(
          os.path.normpath(os.path.join(output_dir, unprocessed_jar_path)))

  source_jar_relative_paths = params.get('bundled_srcjars', [])
  for source_jar_relative_path in source_jar_relative_paths:
    if not source_jar_relative_path.startswith('gen/'):
      continue
    source_jar_path = os.path.join(output_dir, source_jar_relative_path)
    if _is_useful_source_jar(source_jar_path, output_dir):
      source_jar_set.add(source_jar_path)


def _find_params(output_dir: str) -> Iterator[str]:
  """Finds all .params.json files within the output directory.

  It uses list_java_targets.py to enumerate .params.json files, correctly
  ignoring stale ones in the output directory.

  Args:
    output_dir: The path to the build output directory.

  Yields:
    The paths to the .params.json files.
  """
  output = subprocess.check_output(
      [
          os.path.join(_SRC_ROOT, 'build', 'android', 'list_java_targets.py'),
          '--output-directory=' + output_dir,
          '--omit-targets',
          '--print-params-paths',
      ],
      cwd=_SRC_ROOT,
      encoding='utf-8',
  )
  return output.splitlines()


def _scan_params(output_dir: str) -> Tuple[List[str], List[str], List[str]]:
  """Scans the output directory for .params.json files and processes them.

  This function walks through the 'gen' subdirectory of the output directory
  to find all .params.json files and extracts source paths, class paths,
  and source JARs from them.

  Args:
    output_dir: The path to the build output directory.

  Returns:
    A tuple containing:
      - A sorted list of source root directory paths.
      - A sorted list of classpath JAR file paths.
      - A sorted list of source JAR file paths.
  """
  source_path_set: Set[str] = set()
  class_path_set: Set[str] = set()
  source_jar_set: Set[str] = set()

  for params_path in _find_params(output_dir):
    _process_params(params_path, output_dir, source_path_set, class_path_set,
                    source_jar_set)

  return sorted(source_path_set), sorted(class_path_set), sorted(source_jar_set)


def _extract_source_jar(source_jar: str) -> str:
  """Extracts a source JAR file to a directory.

  The extraction is skipped if the JAR has not been modified since the last
  extraction.

  Args:
    source_jar: The path to the source JAR file.

  Returns:
    The path to the directory where the JAR was extracted.
  """
  extract_dir = source_jar + '.extracted-for-vscode'

  # Compare timestamps to avoid extracting source jars on every startup.
  source_jar_mtime = os.stat(source_jar).st_mtime
  try:
    extract_dir_mtime = os.stat(extract_dir).st_mtime
  except OSError:
    extract_dir_mtime = 0
  if source_jar_mtime <= extract_dir_mtime:
    return extract_dir

  logging.info('Extracting %s', source_jar)

  os.makedirs(extract_dir, exist_ok=True)

  # Use `jar` command from the JDK for optimal performance. Python's zipfile is
  # not very fast, and suffer from GIL on parallelizing.
  subprocess.check_call(
      [
          os.path.join(_SRC_ROOT, 'third_party', 'jdk', 'current', 'bin',
                       'jar'),
          '-x',
          '-f',
          os.path.abspath(source_jar),
      ],
      cwd=extract_dir,
      stdout=sys.stderr,
  )

  # Remove org.jni_zero placeholders, if any.
  jni_zero_dir = os.path.join(extract_dir, 'org', 'jni_zero')
  if os.path.exists(jni_zero_dir):
    shutil.rmtree(jni_zero_dir)

  return extract_dir


def _extract_source_jars(source_jars: List[str], output_dir: str) -> List[str]:
  """Extracts a list of source JARs in parallel.

  Before extraction, it ensures that the source JARs themselves are up-to-date
  by attempting to build them.

  Args:
    source_jars: A list of paths to source JAR files.
    output_dir: The path to the build output directory.

  Returns:
    A sorted list of paths to the directories where the source JARs were
    extracted.
  """
  if not source_jars:
    return []

  source_jar_targets = [
      os.path.relpath(source_jar, output_dir) for source_jar in source_jars
  ]
  _compile(output_dir, source_jar_targets)

  # Parallelize extracting source JARs as it takes a significant amount of time
  # to process all JARs for Chromium serially.
  with concurrent.futures.ThreadPoolExecutor() as executor:
    new_source_dirs = executor.map(_extract_source_jar, source_jars)

  return sorted(new_source_dirs)


def _version_main(_options: argparse.Namespace) -> None:
  """Handles the 'version' subcommand. Prints the API version."""
  print(_API_VERSION)


def _build_info_main(options: argparse.Namespace) -> None:
  """Handles the 'build-info' subcommand.

  Gathers build information (source paths, class paths) and prints it
  as JSON.
  """
  _gn_gen(options.output_dir)
  source_roots, class_jars, source_jars = _scan_params(options.output_dir)
  source_roots.extend(_extract_source_jars(source_jars, options.output_dir))

  build_info = BuildInfo(
      source_paths=source_roots,
      class_paths=class_jars,
  )
  json.dump(build_info.to_dict(), sys.stdout, indent=2, sort_keys=True)


def _parse_arguments(args: List[str]) -> argparse.Namespace:
  """Parses command-line arguments for the script."""
  parser = argparse.ArgumentParser(description=__doc__)
  subparsers = parser.add_subparsers(dest='subcommand', required=True)

  version_parser = subparsers.add_parser('version', help='Prints version')
  version_parser.set_defaults(main_func=_version_main)

  build_info_parser = subparsers.add_parser(
      'build-info', help='Returns information needed to build Java files')
  build_info_parser.set_defaults(main_func=_build_info_main)
  build_info_parser.add_argument(
      '--output-dir',
      required=True,
      help='Relative path to the output directory, e.g. "out/Debug"')

  return parser.parse_args(args)


def main(args: List[str]) -> None:
  build_utils.InitLogging('CHROMIUMIDE_API_DEBUG')

  assert os.path.exists('.gn'), 'This script must be run from the src directory'

  options = _parse_arguments(args)
  options.main_func(options)


if __name__ == '__main__':
  main(sys.argv[1:])
