#!/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 apk_utils
import extractmarker
import toolhelper
import utils
import zip_utils

LOWEST_SUPPORTED_MIN_API = 21  # Android L (native multi dex)


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')
    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 main(argv):
    (options, args) = parse_options(argv)
    with utils.TempDir() as temp:
        dex = os.path.join(temp, 'dex.zip')
        d8_args = [
            '--min-api',
            str(
                max(apk_utils.get_min_api(options.apk),
                    LOWEST_SUPPORTED_MIN_API)), '--output', dex,
            '--no-desugaring', '--release'
        ]
        if options.profile:
            d8_args.extend(['--startup-profile', options.profile])
        dex_to_relayout, desugared_library_dex = get_dex_to_relayout(
            options, temp)
        d8_args.extend(dex_to_relayout)
        toolhelper.run('d8',
                       d8_args,
                       build=not options.no_build,
                       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:]))
