#!/usr/bin/env python3
# Copyright (c) 2022, 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 argparse
import os
import subprocess
import sys

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import apk_masseur
import extractmarker
import toolhelper
import utils
import zip_utils

def parse_options(argv):
  result = argparse.ArgumentParser(
      description='Relayout a given APK using a startup profile.')
  result.add_argument('--apk',
                      help='Path to the .apk',
                      required=True)
  result.add_argument('--desugared-library',
                      choices=['auto', 'true', 'false'],
                      default='auto',
                      help='Whether the last dex file of the app is desugared '
                           'library')
  result.add_argument('--no-build',
                      action='store_true',
                      default=False,
                      help='To disable building using gradle')
  result.add_argument('--out',
                      help='Destination of resulting apk',
                      required=True)
  result.add_argument('--profile',
                      help='Path to the startup profile',
                      required=True)
  options, args = result.parse_known_args(argv)
  return options, args

def get_dex_to_relayout(options, temp):
  marker = extractmarker.extractmarker(options.apk, build=not options.no_build)
  if '~~L8' not in marker:
    return [options.apk], None
  dex_dir = os.path.join(temp, 'dex')
  dex_predicate = \
      lambda name : name.startswith('classes') and name.endswith('.dex')
  extracted_dex_files = \
      zip_utils.extract_all_that_matches(options.apk, dex_dir, dex_predicate)
  desugared_library_dex = 'classes%s.dex' % len(extracted_dex_files)
  assert desugared_library_dex in extracted_dex_files
  return [
      os.path.join(dex_dir, name) \
          for name in extracted_dex_files if name != desugared_library_dex], \
      os.path.join(dex_dir, desugared_library_dex)

def has_desugared_library_dex(options):
  if options.desugared_library == 'auto':
    marker = extractmarker.extractmarker(
        options.apk, build=not options.no_build)
    return '~~L8' in marker
  return options.desugared_library == 'true'

def get_min_api(apk):
  aapt = os.path.join(utils.getAndroidBuildTools(), 'aapt')
  cmd = [aapt, 'dump', 'badging', apk]
  stdout = subprocess.check_output(cmd).decode('utf-8').strip()
  for line in stdout.splitlines():
    if line.startswith('sdkVersion:\''):
      return int(line[len('sdkVersion:\''): -1])
  raise ValueError('Unexpected stdout: %s' % stdout)

def main(argv):
  (options, args) = parse_options(argv)
  with utils.TempDir() as temp:
    dex = os.path.join(temp, 'dex.zip')
    d8_args = [
        '--min-api', str(get_min_api(options.apk)),
        '--output', dex,
        '--no-desugaring',
        '--release']
    dex_to_relayout, desugared_library_dex = get_dex_to_relayout(options, temp)
    d8_args.extend(dex_to_relayout)
    extra_args = ['-Dcom.android.tools.r8.startup.profile=%s' % options.profile]
    toolhelper.run(
        'd8',
        d8_args,
        build=not options.no_build,
        extra_args=extra_args,
        main='com.android.tools.r8.D8')
    if desugared_library_dex is not None:
      dex_files = [name for name in \
          zip_utils.get_names_that_matches(dex, lambda x : True)]
      zip_utils.add_file_to_zip(
          desugared_library_dex, 'classes%s.dex' % str(len(dex_files) + 1), dex)
    apk_masseur.masseur(options.apk, dex=dex, out=options.out)

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