#!/usr/bin/env python
#
# Copyright 2016 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.

"""Processes an Android AAR file."""

import argparse
import filecmp
import os
import posixpath
import re
import shutil
import sys
import tempfile
from xml.etree import ElementTree
import zipfile

from util import build_utils

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
                                             os.pardir, os.pardir)))
import gn_helpers


def _IsManifestEmpty(manifest_str):
  """Returns whether the given manifest has merge-worthy elements.

  E.g.: <activity>, <service>, etc.
  """
  doc = ElementTree.fromstring(manifest_str)
  for node in doc:
    if node.tag == 'application':
      if len(node):
        return False
    elif node.tag != 'uses-sdk':
      return False

  return True


def _CreateInfo(aar_file):
  data = {}
  data['aidl'] = []
  data['assets'] = []
  data['resources'] = []
  data['subjars'] = []
  data['subjar_tuples'] = []
  data['has_classes_jar'] = False
  data['has_proguard_flags'] = False
  data['has_native_libraries'] = False
  data['has_r_text_file'] = False
  with zipfile.ZipFile(aar_file) as z:
    data['is_manifest_empty'] = (
        _IsManifestEmpty(z.read('AndroidManifest.xml')))

    for name in z.namelist():
      if name.endswith('/'):
        continue
      if name.startswith('aidl/'):
        data['aidl'].append(name)
      elif name.startswith('res/'):
        data['resources'].append(name)
      elif name.startswith('libs/') and name.endswith('.jar'):
        label = posixpath.basename(name)[:-4]
        label = re.sub(r'[^a-zA-Z0-9._]', '_', label)
        data['subjars'].append(name)
        data['subjar_tuples'].append([label, name])
      elif name.startswith('assets/'):
        data['assets'].append(name)
      elif name.startswith('jni/'):
        data['has_native_libraries'] = True
      elif name == 'classes.jar':
        data['has_classes_jar'] = True
      elif name == 'proguard.txt':
        data['has_proguard_flags'] = True
      elif name == 'R.txt':
        # Some AARs, e.g. gvr_controller_java, have empty R.txt. Such AARs
        # have no resources as well. We treat empty R.txt as having no R.txt.
        data['has_r_text_file'] = (z.read('R.txt').strip() != '')

  return """\
# Generated by //build/android/gyp/aar.py
# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".

""" + gn_helpers.ToGNString(data)


def _AddCommonArgs(parser):
  parser.add_argument('aar_file',
                      help='Path to the AAR file.',
                      type=os.path.normpath)


def main():
  parser = argparse.ArgumentParser(description=__doc__)
  command_parsers = parser.add_subparsers(dest='command')
  subp = command_parsers.add_parser(
      'list', help='Output a GN scope describing the contents of the .aar.')
  _AddCommonArgs(subp)
  subp.add_argument('--output',
                    help='Output file.',
                    default='-')

  subp = command_parsers.add_parser('extract', help='Extracts the .aar')
  _AddCommonArgs(subp)
  subp.add_argument('--output-dir',
                    help='Output directory for the extracted files.',
                    required=True,
                    type=os.path.normpath)
  subp.add_argument('--assert-info-file',
                    help='Path to .info file. Asserts that it matches what '
                         '"list" would output.',
                    type=argparse.FileType('r'))

  args = parser.parse_args()

  if args.command == 'extract':
    if args.assert_info_file:
      expected = _CreateInfo(args.aar_file)
      actual = args.assert_info_file.read()
      if actual != expected:
        raise Exception('android_aar_prebuilt() cached .info file is '
                        'out-of-date. Run gn gen with '
                        'update_android_aar_prebuilts=true to update it.')

    # Clear previously extracted versions of the AAR if it is obsolete.
    with build_utils.TempDir() as tmp_root:
      build_utils.ExtractAll(args.aar_file, path=tmp_root)

      # Compare files and copy/delete if necessary.
      dcmp = filecmp.dircmp(args.output_dir, tmp_root, ignore=[])
      for f in dcmp.left_only:
        shutil.rmtree(os.path.join(args.output_dir, f), ignore_errors=True)

      for f in dcmp.right_list:
        tmp_path = os.path.join(tmp_root, f)
        dst = os.path.join(args.output_dir, f)
        if os.path.isdir(tmp_path):
          build_utils.MakeDirectory(dst)
          continue

        if os.path.isdir(dst):
          shutil.rmtree(dst, ignore_errors=True)
        elif os.path.isfile(dst) and filecmp.cmp(dst, tmp_path, shallow=False):
          continue
        shutil.copy(tmp_path, dst)

  elif args.command == 'list':
    aar_info = _CreateInfo(args.aar_file)
    aar_output_present = args.output != '-' and os.path.isfile(args.output)
    if aar_output_present:
      # Some .info files are read-only, for examples the cipd-controlled ones
      # under third_party/android_deps/repositoty. To deal with these, first
      # that its content is correct, and if it is, exit without touching
      # the file system.
      file_info = open(args.output, 'r').read()
      if file_info == aar_info:
        return

    # Try to write the file. This may fail for read-only ones that were
    # not updated.
    try:
      with open(args.output, 'w') as f:
        f.write(aar_info)
    except IOError as e:
      if not aar_output_present:
        raise e
      raise Exception('Could not update output file: %s\n%s\n' %
                      (args.output, e))

if __name__ == '__main__':
  sys.exit(main())
