#!/usr/bin/env python3
# Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

import glob
import optparse
import os
import shutil
import sys

import apk_utils
import utils
import zip_utils

USAGE = 'usage: %prog [options] <apk>'

def parse_options():
  parser = optparse.OptionParser(usage=USAGE)
  parser.add_option('--clear-profile',
                    help='To remove baseline.prof and baseline.profm from '
                         'assets/dexopt/',
                    default=False,
                    action='store_true')
  parser.add_option('--dex',
                    help='Directory or archive with dex files to use instead '
                         'of those in the apk',
                    default=None)
  parser.add_option('--desugared-library-dex',
                    help='Path to desugared library dex file to use or archive '
                         'containing a single classes.dex file',
                    default=None)
  parser.add_option('--resources',
                    help=('pattern that matches resources to use instead of '
                        + 'those in the apk'),
                    default=None)
  parser.add_option('--out',
                    help='output file (default ./$(basename <apk>))',
                    default=None)
  parser.add_option('--keystore',
                    help='keystore file (default ~/.android/app.keystore)',
                    default=None)
  parser.add_option('--install',
                    help='install the generated apk with adb options -t -r -d',
                    default=False,
                    action='store_true')
  parser.add_option('--adb-options',
                    help='additional adb options when running adb',
                    default=None)
  parser.add_option('--quiet',
                    help='disable verbose logging',
                    default=False)
  parser.add_option('--sign-before-align',
                    help='Sign the apk before aligning',
                    default=False,
                    action='store_true')
  (options, args) = parser.parse_args()
  if len(args) != 1:
    parser.error('Expected <apk> argument, got: ' + ' '.join(args))
  apk = args[0]
  return (options, apk)

def is_archive(file):
  return file.endswith('.zip') or file.endswith('.jar')

def repack(
    apk, clear_profile, processed_out, desugared_library_dex, resources, temp,
    quiet, logging):
  processed_apk = os.path.join(temp, 'processed.apk')
  shutil.copyfile(apk, processed_apk)

  if clear_profile:
    zip_utils.remove_files_from_zip(
        ['assets/dexopt/baseline.prof', 'assets/dexopt/baseline.profm'],
        processed_apk)

  if not processed_out:
    utils.Print('Using original dex as is', quiet=quiet)
    return processed_apk

  utils.Print(
      'Repacking APK with dex files from {}'.format(processed_out), quiet=quiet)

  # Delete original dex files in APK.
  with utils.ChangedWorkingDirectory(temp, quiet=quiet):
    cmd = ['zip', '-d', 'processed.apk', '*.dex']
    utils.RunCmd(cmd, quiet=quiet, logging=logging)

  # Unzip the jar or zip file into `temp`.
  if is_archive(processed_out):
    cmd = ['unzip', processed_out, '-d', temp]
    if quiet:
      cmd.insert(1, '-q')
    utils.RunCmd(cmd, quiet=quiet, logging=logging)
    processed_out = temp
  elif desugared_library_dex:
    for dex_name in glob.glob('*.dex', root_dir=processed_out):
      src = os.path.join(processed_out, dex_name)
      dst = os.path.join(temp, dex_name)
      shutil.copyfile(src, dst)
    processed_out = temp

  if desugared_library_dex:
    desugared_library_dex_index = len(glob.glob('*.dex', root_dir=temp)) + 1
    desugared_library_dex_name = 'classes%s.dex' % desugared_library_dex_index
    desugared_library_dex_dst = os.path.join(temp, desugared_library_dex_name)
    if is_archive(desugared_library_dex):
      zip_utils.extract_member(
          desugared_library_dex, 'classes.dex', desugared_library_dex_dst)
    else:
      shutil.copyfile(desugared_library_dex, desugared_library_dex_dst)

  # Insert the new dex and resource files from `processed_out` into the APK.
  with utils.ChangedWorkingDirectory(processed_out, quiet=quiet):
    dex_files = glob.glob('*.dex')
    dex_files.sort()
    resource_files = glob.glob(resources) if resources else []
    cmd = ['zip', '-u', '-0', processed_apk] + dex_files + resource_files
    utils.RunCmd(cmd, quiet=quiet, logging=logging)
  return processed_apk

def sign(unsigned_apk, keystore, temp, quiet, logging):
  signed_apk = os.path.join(temp, 'unaligned.apk')
  return apk_utils.sign_with_apksigner(
      unsigned_apk, signed_apk, keystore, quiet=quiet, logging=logging)

def align(signed_apk, temp, quiet, logging):
  utils.Print('Aligning', quiet=quiet)
  aligned_apk = os.path.join(temp, 'aligned.apk')
  return apk_utils.align(signed_apk, aligned_apk)

def masseur(
    apk, clear_profile=False, dex=None, desugared_library_dex=None,
    resources=None, out=None, adb_options=None, sign_before_align=False,
    keystore=None, install=False, quiet=False, logging=True):
  if not out:
    out = os.path.basename(apk)
  if not keystore:
    keystore = apk_utils.default_keystore()
  with utils.TempDir() as temp:
    processed_apk = None
    if dex or clear_profile:
      processed_apk = repack(
          apk, clear_profile, dex, desugared_library_dex, resources, temp,
          quiet, logging)
    else:
      assert not desugared_library_dex
      utils.Print(
          'Signing original APK without modifying apk', quiet=quiet)
      processed_apk = os.path.join(temp, 'processed.apk')
      shutil.copyfile(apk, processed_apk)
    if sign_before_align:
      signed_apk = sign(
          processed_apk, keystore, temp, quiet=quiet, logging=logging)
      aligned_apk = align(signed_apk, temp, quiet=quiet, logging=logging)
      utils.Print('Writing result to {}'.format(out), quiet=quiet)
      shutil.copyfile(aligned_apk, out)
    else:
      aligned_apk = align(processed_apk, temp, quiet=quiet, logging=logging)
      signed_apk = sign(
          aligned_apk, keystore, temp, quiet=quiet, logging=logging)
      utils.Print('Writing result to {}'.format(out), quiet=quiet)
      shutil.copyfile(signed_apk, out)
    if install:
      adb_cmd = ['adb']
      if adb_options:
        adb_cmd.extend(
            [option for option in adb_options.split(' ') if option])
      adb_cmd.extend(['install', '-t', '-r', '-d', out]);
      utils.RunCmd(adb_cmd, quiet=quiet, logging=logging)

def main():
  (options, apk) = parse_options()
  masseur(apk, **vars(options))
  return 0

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