#!/usr/bin/env python
#
# Copyright (c) 2012 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.

"""Process Android resources to generate R.java, and prepare for packaging.

This will crunch images and generate v14 compatible resources
(see generate_v14_compatible_resources.py).
"""

import codecs
import optparse
import os
import re
import shutil
import sys
import zipfile

import generate_v14_compatible_resources

from util import build_utils

# Import jinja2 from third_party/jinja2
sys.path.insert(1,
    os.path.join(os.path.dirname(__file__), '../../../third_party'))
from jinja2 import Template # pylint: disable=F0401


def ParseArgs(args):
  """Parses command line options.

  Returns:
    An options object as from optparse.OptionsParser.parse_args()
  """
  parser = optparse.OptionParser()
  build_utils.AddDepfileOption(parser)

  parser.add_option('--android-sdk', help='path to the Android SDK folder')
  parser.add_option('--aapt-path',
                    help='path to the Android aapt tool')
  parser.add_option('--non-constant-id', action='store_true')

  parser.add_option('--android-manifest', help='AndroidManifest.xml path')
  parser.add_option('--custom-package', help='Java package for R.java')
  parser.add_option(
      '--shared-resources',
      action='store_true',
      help='Make a resource package that can be loaded by a different'
      'application at runtime to access the package\'s resources.')

  parser.add_option('--resource-dirs',
                    help='Directories containing resources of this target.')
  parser.add_option('--dependencies-res-zips',
                    help='Resources from dependents.')

  parser.add_option('--resource-zip-out',
                    help='Path for output zipped resources.')

  parser.add_option('--R-dir',
                    help='directory to hold generated R.java.')
  parser.add_option('--srcjar-out',
                    help='Path to srcjar to contain generated R.java.')
  parser.add_option('--r-text-out',
                    help='Path to store the R.txt file generated by appt.')

  parser.add_option('--proguard-file',
                    help='Path to proguard.txt generated file')

  parser.add_option(
      '--v14-skip',
      action="store_true",
      help='Do not generate nor verify v14 resources')

  parser.add_option(
      '--extra-res-packages',
      help='Additional package names to generate R.java files for')
  parser.add_option(
      '--extra-r-text-files',
      help='For each additional package, the R.txt file should contain a '
      'list of resources to be included in the R.java file in the format '
      'generated by aapt')
  parser.add_option(
      '--include-all-resources',
      action='store_true',
      help='Include every resource ID in every generated R.java file '
      '(ignoring R.txt).')

  parser.add_option(
      '--all-resources-zip-out',
      help='Path for output of all resources. This includes resources in '
      'dependencies.')

  parser.add_option('--stamp', help='File to touch on success')

  (options, args) = parser.parse_args(args)

  if args:
    parser.error('No positional arguments should be given.')

  # Check that required options have been provided.
  required_options = (
      'android_sdk',
      'aapt_path',
      'android_manifest',
      'dependencies_res_zips',
      'resource_dirs',
      'resource_zip_out',
      )
  build_utils.CheckOptions(options, parser, required=required_options)

  if (options.R_dir is None) == (options.srcjar_out is None):
    raise Exception('Exactly one of --R-dir or --srcjar-out must be specified.')

  return options


def CreateExtraRJavaFiles(
      r_dir, extra_packages, extra_r_text_files, shared_resources, include_all):
  if include_all:
    java_files = build_utils.FindInDirectory(r_dir, "R.java")
    if len(java_files) != 1:
      return
    r_java_file = java_files[0]
    r_java_contents = codecs.open(r_java_file, encoding='utf-8').read()

    for package in extra_packages:
      package_r_java_dir = os.path.join(r_dir, *package.split('.'))
      build_utils.MakeDirectory(package_r_java_dir)
      package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
      new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package,
                          r_java_contents)
      codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java)
  else:
    if len(extra_packages) != len(extra_r_text_files):
      raise Exception('Need one R.txt file per extra package')

    all_resources = {}
    r_txt_file = os.path.join(r_dir, 'R.txt')
    if not os.path.exists(r_txt_file):
      return
    with open(r_txt_file) as f:
      for line in f:
        m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
        if not m:
          raise Exception('Unexpected line in R.txt: %s' % line)
        java_type, resource_type, name, value = m.groups()
        all_resources[(resource_type, name)] = (java_type, value)

    for package, r_text_file in zip(extra_packages, extra_r_text_files):
      if os.path.exists(r_text_file):
        package_r_java_dir = os.path.join(r_dir, *package.split('.'))
        build_utils.MakeDirectory(package_r_java_dir)
        package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
        CreateExtraRJavaFile(
            package, package_r_java_path, r_text_file, all_resources,
            shared_resources)


def CreateExtraRJavaFile(
      package, r_java_path, r_text_file, all_resources, shared_resources):
  resources = {}
  with open(r_text_file) as f:
    for line in f:
      m = re.match(r'int(?:\[\])? (\w+) (\w+) ', line)
      if not m:
        raise Exception('Unexpected line in R.txt: %s' % line)
      resource_type, name = m.groups()
      java_type, value = all_resources[(resource_type, name)]
      if resource_type not in resources:
        resources[resource_type] = []
      resources[resource_type].append((name, java_type, value))

  template = Template("""/* AUTO-GENERATED FILE.  DO NOT MODIFY. */

package {{ package }};

public final class R {
    {% for resource_type in resources %}
    public static final class {{ resource_type }} {
        {% for name, java_type, value in resources[resource_type] %}
        {% if shared_resources %}
        public static {{ java_type }} {{ name }} = {{ value }};
        {% else %}
        public static final {{ java_type }} {{ name }} = {{ value }};
        {% endif %}
        {% endfor %}
    }
    {% endfor %}
    {% if shared_resources %}
    public static void onResourcesLoaded(int packageId) {
        {% for resource_type in resources %}
        {% for name, java_type, value in resources[resource_type] %}
        {% if java_type == 'int[]' %}
        for(int i = 0; i < {{ resource_type }}.{{ name }}.length; ++i) {
            {{ resource_type }}.{{ name }}[i] =
                    ({{ resource_type }}.{{ name }}[i] & 0x00ffffff)
                    | (packageId << 24);
        }
        {% else %}
        {{ resource_type }}.{{ name }} =
                ({{ resource_type }}.{{ name }} & 0x00ffffff)
                | (packageId << 24);
        {% endif %}
        {% endfor %}
        {% endfor %}
    }
    {% endif %}
}
""", trim_blocks=True, lstrip_blocks=True)

  output = template.render(package=package, resources=resources,
                           shared_resources=shared_resources)
  with open(r_java_path, 'w') as f:
    f.write(output)


def CrunchDirectory(aapt, input_dir, output_dir):
  """Crunches the images in input_dir and its subdirectories into output_dir.

  If an image is already optimized, crunching often increases image size. In
  this case, the crunched image is overwritten with the original image.
  """
  aapt_cmd = [aapt,
              'crunch',
              '-C', output_dir,
              '-S', input_dir,
              '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
  build_utils.CheckOutput(aapt_cmd, stderr_filter=FilterCrunchStderr,
                          fail_func=DidCrunchFail)

  # Check for images whose size increased during crunching and replace them
  # with their originals (except for 9-patches, which must be crunched).
  for dir_, _, files in os.walk(output_dir):
    for crunched in files:
      if crunched.endswith('.9.png'):
        continue
      if not crunched.endswith('.png'):
        raise Exception('Unexpected file in crunched dir: ' + crunched)
      crunched = os.path.join(dir_, crunched)
      original = os.path.join(input_dir, os.path.relpath(crunched, output_dir))
      original_size = os.path.getsize(original)
      crunched_size = os.path.getsize(crunched)
      if original_size < crunched_size:
        shutil.copyfile(original, crunched)


def FilterCrunchStderr(stderr):
  """Filters out lines from aapt crunch's stderr that can safely be ignored."""
  filtered_lines = []
  for line in stderr.splitlines(True):
    # Ignore this libpng warning, which is a known non-error condition.
    # http://crbug.com/364355
    if ('libpng warning: iCCP: Not recognizing known sRGB profile that has '
        + 'been edited' in line):
      continue
    filtered_lines.append(line)
  return ''.join(filtered_lines)


def DidCrunchFail(returncode, stderr):
  """Determines whether aapt crunch failed from its return code and output.

  Because aapt's return code cannot be trusted, any output to stderr is
  an indication that aapt has failed (http://crbug.com/314885).
  """
  return returncode != 0 or stderr


def ZipResources(resource_dirs, zip_path):
  # Python zipfile does not provide a way to replace a file (it just writes
  # another file with the same name). So, first collect all the files to put
  # in the zip (with proper overriding), and then zip them.
  files_to_zip = dict()
  for d in resource_dirs:
    for root, _, files in os.walk(d):
      for f in files:
        archive_path = os.path.join(os.path.relpath(root, d), f)
        path = os.path.join(root, f)
        files_to_zip[archive_path] = path
  with zipfile.ZipFile(zip_path, 'w') as outzip:
    for archive_path, path in files_to_zip.iteritems():
      outzip.write(path, archive_path)


def CombineZips(zip_files, output_path):
  # When packaging resources, if the top-level directories in the zip file are
  # of the form 0, 1, ..., then each subdirectory will be passed to aapt as a
  # resources directory. While some resources just clobber others (image files,
  # etc), other resources (particularly .xml files) need to be more
  # intelligently merged. That merging is left up to aapt.
  with zipfile.ZipFile(output_path, 'w') as outzip:
    for i, z in enumerate(zip_files):
      with zipfile.ZipFile(z, 'r') as inzip:
        for name in inzip.namelist():
          new_name = '%d/%s' % (i, name)
          outzip.writestr(new_name, inzip.read(name))


def main():
  args = build_utils.ExpandFileArgs(sys.argv[1:])

  options = ParseArgs(args)
  android_jar = os.path.join(options.android_sdk, 'android.jar')
  aapt = options.aapt_path

  input_files = []

  with build_utils.TempDir() as temp_dir:
    deps_dir = os.path.join(temp_dir, 'deps')
    build_utils.MakeDirectory(deps_dir)
    v14_dir = os.path.join(temp_dir, 'v14')
    build_utils.MakeDirectory(v14_dir)

    gen_dir = os.path.join(temp_dir, 'gen')
    build_utils.MakeDirectory(gen_dir)

    input_resource_dirs = build_utils.ParseGypList(options.resource_dirs)

    if not options.v14_skip:
      for resource_dir in input_resource_dirs:
        generate_v14_compatible_resources.GenerateV14Resources(
            resource_dir,
            v14_dir)

    dep_zips = build_utils.ParseGypList(options.dependencies_res_zips)
    input_files += dep_zips
    dep_subdirs = []
    for z in dep_zips:
      subdir = os.path.join(deps_dir, os.path.basename(z))
      if os.path.exists(subdir):
        raise Exception('Resource zip name conflict: ' + os.path.basename(z))
      build_utils.ExtractAll(z, path=subdir)
      dep_subdirs.append(subdir)

    # Generate R.java. This R.java contains non-final constants and is used only
    # while compiling the library jar (e.g. chromium_content.jar). When building
    # an apk, a new R.java file with the correct resource -> ID mappings will be
    # generated by merging the resources from all libraries and the main apk
    # project.
    package_command = [aapt,
                       'package',
                       '-m',
                       '-M', options.android_manifest,
                       '--auto-add-overlay',
                       '-I', android_jar,
                       '--output-text-symbols', gen_dir,
                       '-J', gen_dir,
                       '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]

    for d in input_resource_dirs:
      package_command += ['-S', d]

    for d in dep_subdirs:
      package_command += ['-S', d]

    if options.non_constant_id:
      package_command.append('--non-constant-id')
    if options.custom_package:
      package_command += ['--custom-package', options.custom_package]
    if options.proguard_file:
      package_command += ['-G', options.proguard_file]
    if options.shared_resources:
      package_command.append('--shared-lib')
    build_utils.CheckOutput(package_command, print_stderr=False)

    if options.extra_res_packages:
      CreateExtraRJavaFiles(
          gen_dir,
          build_utils.ParseGypList(options.extra_res_packages),
          build_utils.ParseGypList(options.extra_r_text_files),
          options.shared_resources,
          options.include_all_resources)

    # This is the list of directories with resources to put in the final .zip
    # file. The order of these is important so that crunched/v14 resources
    # override the normal ones.
    zip_resource_dirs = input_resource_dirs + [v14_dir]

    base_crunch_dir = os.path.join(temp_dir, 'crunch')

    # Crunch image resources. This shrinks png files and is necessary for
    # 9-patch images to display correctly. 'aapt crunch' accepts only a single
    # directory at a time and deletes everything in the output directory.
    for idx, input_dir in enumerate(input_resource_dirs):
      crunch_dir = os.path.join(base_crunch_dir, str(idx))
      build_utils.MakeDirectory(crunch_dir)
      zip_resource_dirs.append(crunch_dir)
      CrunchDirectory(aapt, input_dir, crunch_dir)

    ZipResources(zip_resource_dirs, options.resource_zip_out)

    if options.all_resources_zip_out:
      CombineZips([options.resource_zip_out] + dep_zips,
                  options.all_resources_zip_out)

    if options.R_dir:
      build_utils.DeleteDirectory(options.R_dir)
      shutil.copytree(gen_dir, options.R_dir)
    else:
      build_utils.ZipDir(options.srcjar_out, gen_dir)

    if options.r_text_out:
      r_text_path = os.path.join(gen_dir, 'R.txt')
      if os.path.exists(r_text_path):
        shutil.copyfile(r_text_path, options.r_text_out)
      else:
        open(options.r_text_out, 'w').close()

  if options.depfile:
    input_files += build_utils.GetPythonDependencies()
    build_utils.WriteDepfile(options.depfile, input_files)

  if options.stamp:
    build_utils.Touch(options.stamp)


if __name__ == '__main__':
  main()
