#!/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(['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())
