#!/usr/bin/env python3

# 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.

"""Creates size-info/*.info files used by SuperSize."""

import argparse
import collections
import os
import re
import sys
import zipfile

from util import build_utils
from util import jar_info_utils


_AAR_VERSION_PATTERN = re.compile(r'/[^/]*?(\.aar/|\.jar/)')


def _RemoveDuplicatesFromList(source_list):
  return collections.OrderedDict.fromkeys(source_list).keys()


def _TransformAarPaths(path):
  # .aar files within //third_party/android_deps have a version suffix.
  # The suffix changes each time .aar files are updated, which makes size diffs
  # hard to compare (since the before/after have different source paths).
  # Rather than changing how android_deps works, we employ this work-around
  # to normalize the paths.
  # From: .../androidx_appcompat_appcompat/appcompat-1.1.0.aar/res/...
  #   To: .../androidx_appcompat_appcompat.aar/res/...
  # https://crbug.com/1056455
  if 'android_deps' not in path:
    return path
  return _AAR_VERSION_PATTERN.sub(r'\1', path)


def _MergeResInfoFiles(res_info_path, info_paths):
  # Concatenate them all.
  # only_if_changed=False since no build rules depend on this as an input.
  with build_utils.AtomicOutput(res_info_path, only_if_changed=False,
                                mode='w+') as dst:
    for p in info_paths:
      with open(p) as src:
        dst.writelines(_TransformAarPaths(l) for l in src)


def _PakInfoPathsForAssets(assets):
  return [f.split(':')[0] + '.info' for f in assets if f.endswith('.pak')]


def _MergePakInfoFiles(merged_path, pak_infos):
  info_lines = set()
  for pak_info_path in pak_infos:
    with open(pak_info_path, 'r') as src_info_file:
      info_lines.update(_TransformAarPaths(x) for x in src_info_file)
  # only_if_changed=False since no build rules depend on this as an input.
  with build_utils.AtomicOutput(merged_path, only_if_changed=False,
                                mode='w+') as f:
    f.writelines(sorted(info_lines))


def _FullJavaNameFromClassFilePath(path):
  # Input:  base/android/java/src/org/chromium/Foo.class
  # Output: base.android.java.src.org.chromium.Foo
  if not path.endswith('.class'):
    return ''
  path = os.path.splitext(path)[0]
  parts = []
  while path:
    # Use split to be platform independent.
    head, tail = os.path.split(path)
    path = head
    parts.append(tail)
  parts.reverse()  # Package comes first
  return '.'.join(parts)


def _MergeJarInfoFiles(output, inputs):
  """Merge several .jar.info files to generate an .apk.jar.info.

  Args:
    output: output file path.
    inputs: List of .jar.info or .jar files.
  """
  info_data = dict()
  for path in inputs:
    # For non-prebuilts: .jar.info files are written by compile_java.py and map
    # .class files to .java source paths.
    #
    # For prebuilts: No .jar.info file exists, we scan the .jar files here and
    # map .class files to the .jar.
    #
    # For .aar files: We look for a "source.info" file in the containing
    # directory in order to map classes back to the .aar (rather than mapping
    # them to the extracted .jar file).
    if path.endswith('.info'):
      info_data.update(jar_info_utils.ParseJarInfoFile(path))
    else:
      attributed_path = path
      if not path.startswith('..'):
        parent_path = os.path.dirname(path)
        # See if it's an sub-jar within the .aar.
        if os.path.basename(parent_path) == 'libs':
          parent_path = os.path.dirname(parent_path)
        aar_source_info_path = os.path.join(parent_path, 'source.info')
        # source.info files exist only for jars from android_aar_prebuilt().
        # E.g. Could have an java_prebuilt() pointing to a generated .jar.
        if os.path.exists(aar_source_info_path):
          attributed_path = jar_info_utils.ReadAarSourceInfo(
              aar_source_info_path)

      with zipfile.ZipFile(path) as zip_info:
        for name in zip_info.namelist():
          fully_qualified_name = _FullJavaNameFromClassFilePath(name)
          if fully_qualified_name:
            info_data[fully_qualified_name] = _TransformAarPaths('{}/{}'.format(
                attributed_path, name))

  # only_if_changed=False since no build rules depend on this as an input.
  with build_utils.AtomicOutput(output, only_if_changed=False) as f:
    jar_info_utils.WriteJarInfoFile(f, info_data)


def _FindJarInputs(jar_paths):
  ret = []
  for jar_path in jar_paths:
    jar_info_path = jar_path + '.info'
    if os.path.exists(jar_info_path):
      ret.append(jar_info_path)
    else:
      ret.append(jar_path)
  return ret


def main(args):
  args = build_utils.ExpandFileArgs(args)
  parser = argparse.ArgumentParser(description=__doc__)
  build_utils.AddDepfileOption(parser)
  parser.add_argument(
      '--jar-info-path', required=True, help='Output .jar.info file')
  parser.add_argument(
      '--pak-info-path', required=True, help='Output .pak.info file')
  parser.add_argument(
      '--res-info-path', required=True, help='Output .res.info file')
  parser.add_argument(
      '--jar-files',
      required=True,
      action='append',
      help='GN-list of .jar file paths')
  parser.add_argument(
      '--assets',
      required=True,
      action='append',
      help='GN-list of files to add as assets in the form '
      '"srcPath:zipPath", where ":zipPath" is optional.')
  parser.add_argument(
      '--uncompressed-assets',
      required=True,
      action='append',
      help='Same as --assets, except disables compression.')
  parser.add_argument(
      '--in-res-info-path',
      required=True,
      action='append',
      help='Paths to .ap_.info files')

  options = parser.parse_args(args)

  options.jar_files = build_utils.ParseGnList(options.jar_files)
  options.assets = build_utils.ParseGnList(options.assets)
  options.uncompressed_assets = build_utils.ParseGnList(
      options.uncompressed_assets)

  jar_inputs = _FindJarInputs(_RemoveDuplicatesFromList(options.jar_files))
  pak_inputs = _PakInfoPathsForAssets(options.assets +
                                      options.uncompressed_assets)
  res_inputs = options.in_res_info_path

  # Just create the info files every time. See https://crbug.com/1045024
  _MergeJarInfoFiles(options.jar_info_path, jar_inputs)
  _MergePakInfoFiles(options.pak_info_path, pak_inputs)
  _MergeResInfoFiles(options.res_info_path, res_inputs)

  all_inputs = jar_inputs + pak_inputs + res_inputs
  build_utils.WriteDepfile(options.depfile,
                           options.jar_info_path,
                           inputs=all_inputs)


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