#!/usr/bin/env python3
# Copyright (c) 2021, 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 shutil
import sys
import zipfile

import jdk
import utils
import zip_utils

VERSION_EXTRACTOR = """
import com.android.tools.r8.Version;
public class VersionExtractor {
  public static void main(String[] args) {
    System.out.println(Version.LABEL);
  }
}
"""


def parse_options():
    parser = argparse.ArgumentParser(description='Tag R8 Versions')
    parser.add_argument('--classpath',
                        action='append',
                        help='Dependencies to add to classpath')
    parser.add_argument('--debug-agent',
                        action='store_true',
                        default=False,
                        help='Create a socket for debugging')
    parser.add_argument('--replace-from-jar',
                        default=None,
                        help='Replace output jar with classes from this jar.')
    parser.add_argument(
        '--excldeps-variant',
        action='store_true',
        default=False,
        help='Mark this artifact as an "excldeps" variant of the compiler')
    parser.add_argument('--debug-variant',
                        action='store_true',
                        default=False,
                        help='Compile with debug flag')
    parser.add_argument('--disable-keep-annotations',
                        action='store_true',
                        default=False,
                        help='Disable keep annotations')
    parser.add_argument(
        '--exclude-api-database',
        action='store_true',
        default=False,
        help='Exclude api database (resources/new_api_database.ser)')
    parser.add_argument(
        '--lib',
        action='append',
        help='Additional libraries (JDK 1.8 rt.jar already included)')
    parser.add_argument('--output',
                        required=True,
                        help='The output path for the r8lib')
    parser.add_argument('--pg-conf', action='append', help='Keep configuration')
    parser.add_argument('--pg-map',
                        default=None,
                        help='Input map for distribution and composition')
    parser.add_argument('--r8jar', required=True, help='The R8 jar to compile')
    parser.add_argument('--r8-version-jar',
                        default=None,
                        help='The R8 jar to provide version')
    parser.add_argument('--r8compiler',
                        default='build/libs/r8_with_deps.jar',
                        help='The R8 compiler to use')
    return parser.parse_args()


def get_r8_version(r8jar):
    with utils.TempDir() as temp:
        name = os.path.join(temp, "VersionExtractor.java")
        fd = open(name, 'w')
        fd.write(VERSION_EXTRACTOR)
        fd.close()
        cmd = [jdk.GetJavacExecutable(), '-cp', r8jar, name]
        print(' '.join(cmd))
        cp_separator = ';' if utils.IsWindows() else ':'
        subprocess.check_call(cmd)
        output = subprocess.check_output([
            jdk.GetJavaExecutable(), '-cp',
            cp_separator.join([r8jar, os.path.dirname(name)]),
            'VersionExtractor'
        ]).decode('UTF-8').strip()
        if output == 'main':
            return subprocess.check_output(['git', 'rev-parse',
                                            'HEAD']).decode('UTF-8').strip()
        else:
            return output


# Used to delete the API database when building processkeeprules.jar.
def exclude_api_database(r8jar):
    zip_utils.remove_files_from_zip(
        [os.path.join('resources', 'new_api_database.ser')], r8jar)


# Used to move r8 assistant runtime files into r8.jar.
#
# These files need to be equivalent to the javac generated versions,
# so we copy them in after r8lib has been built.
def replace_in_jar(r8jar, replace_from):
    with utils.TempDir() as temp:
        result = os.path.join(temp, 'result.jar')
        skip_from_r8jar = set()
        with zipfile.ZipFile(result, 'w') as output_file:
            with zipfile.ZipFile(replace_from, 'r') as input_file:
                for zipinfo in input_file.infolist():
                    if zipinfo.filename.endswith('.class'):
                        data = input_file.read(zipinfo)
                        zipinfo.date_time = (1980, 1, 1, 0, 0, 0)
                        output_file.writestr(zipinfo, data)
                        skip_from_r8jar.add(zipinfo.filename)
                    else:
                        assert (zipinfo.filename == 'META-INF/MANIFEST.MF' or
                                zipinfo.is_dir())
            with zipfile.ZipFile(r8jar, 'r') as input_file:
                for zipinfo in input_file.infolist():
                    if not zipinfo.filename in skip_from_r8jar:
                        output_file.writestr(zipinfo, input_file.read(zipinfo))
        shutil.copyfile(result, r8jar)


def main():
    args = parse_options()
    if not os.path.exists(args.r8jar):
        print("Could not find jar: " + args.r8jar)
        return 1
    version = get_r8_version(
        args.r8_version_jar if args.r8_version_jar else args.r8jar)
    variant = '+excldeps' if args.excldeps_variant else ''
    map_id_template = version + variant
    source_file_template = 'R8_%MAP_ID_%MAP_HASH'
    # TODO(b/139725780): See if we can remove or lower the heap size (-Xmx8g).
    cmd = [jdk.GetJavaExecutable(), '-Xmx8g', '-ea']
    if args.debug_agent:
        cmd.extend([
            '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005'
        ])
    cmd.append('-Dcom.android.tools.r8.enableKeepAnnotations=' +
               str(not args.disable_keep_annotations).lower())
    # TODO(b/356344563): Remove when this is default.
    cmd.append(
        '-Dcom.android.tools.r8.enableEmptyMemberRulesToDefaultInitRuleConversion=0'
    )
    cmd.append('-Dcom.android.tools.r8.tracereferences.obfuscateAllEnums')
    cmd.extend(['-cp', args.r8compiler, 'com.android.tools.r8.R8'])
    cmd.append(args.r8jar)
    if args.debug_variant:
        cmd.append('--debug')
    cmd.append('--classfile')
    cmd.extend(['--map-id-template', map_id_template])
    cmd.extend(['--source-file-template', source_file_template])
    cmd.extend(['--output', args.output])
    cmd.extend(['--pg-conf-output', args.output + '.config'])
    cmd.extend(['--pg-map-output', args.output + '.map'])
    cmd.extend(['--partition-map-output', args.output + '_map.zip'])
    cmd.extend(['--lib', jdk.GetDefaultJdkHome()])
    if args.pg_conf:
        for pgconf in args.pg_conf:
            cmd.extend(['--pg-conf', pgconf])
    if args.lib:
        for lib in args.lib:
            cmd.extend(['--lib', lib])
    if args.classpath:
        for cp in args.classpath:
            cmd.extend(['--classpath', cp])
    if args.pg_map:
        cmd.extend(['--pg-map', args.pg_map])
    print(' '.join(cmd))
    subprocess.check_call(cmd)
    if args.exclude_api_database:
        exclude_api_database(args.output)
    if args.replace_from_jar:
        replace_in_jar(args.output, args.replace_from_jar)


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