#!/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

import compiledump
import gradle
import jdk
import utils

GOLEM_BUILD_TARGETS_TESTS = [
    utils.GRADLE_TASK_ALL_TESTS_WITH_APPLY_MAPPING_JAR,
    utils.GRADLE_TASK_TESTBASE_WITH_APPLY_MAPPING_JAR,
    utils.GRADLE_TASK_TEST_DEPS_JAR
]
GOLEM_BUILD_TARGETS = [
    utils.GRADLE_TASK_R8LIB, utils.GRADLE_TASK_KEEP_ANNO_JAR
] + GOLEM_BUILD_TARGETS_TESTS


def get_golem_resource_path(benchmark):
    return os.path.join('benchmarks', benchmark)


def get_jdk_home(options, benchmark):
    if options.golem:
        return os.path.join(get_golem_resource_path(benchmark), 'linux')
    return None


def parse_options(argv):
    result = argparse.ArgumentParser(description='Run test-based benchmarks.')
    result.add_argument('--golem',
                        help='Indicate this as a run on golem',
                        default=False,
                        action='store_true')
    result.add_argument('--benchmark',
                        help='The test benchmark to run',
                        required=True)
    result.add_argument(
        '--target',
        help='The test target to run',
        required=True,
        # These should 1:1 with benchmarks/BenchmarkTarget.java
        choices=['d8', 'r8-full', 'r8-force', 'r8-compat', 'retrace'])
    result.add_argument(
        '--debug-agent',
        '--debug_agent',
        help=
        'Enable Java debug agent and suspend compilation (default disabled)',
        default=False,
        action='store_true')
    result.add_argument('--nolib',
                        '--no-lib',
                        '--no-r8lib',
                        help='Run the non-lib R8 build (default false)',
                        default=False,
                        action='store_true')
    result.add_argument('--no-build',
                        '--no_build',
                        help='Run without building first (default false)',
                        default=False,
                        action='store_true')
    result.add_argument('--enable-assertions',
                        '--enable_assertions',
                        '-ea',
                        help='Enable assertions when running',
                        default=False,
                        action='store_true')
    result.add_argument('--iterations',
                        '-i',
                        help='Number of iterations to run',
                        type=int)
    result.add_argument('--output',
                        help='Output path where to write the result')
    result.add_argument('--print-times',
                        help='Print timing information from r8',
                        default=False,
                        action='store_true')
    result.add_argument(
        '--version',
        '-v',
        help='Use R8 version/hash for the run (default local build)',
        default=None)
    result.add_argument(
        '--version-jar',
        help='The r8.jar corresponding to the version given at --version.',
        default=None)
    result.add_argument('--temp',
                        help='A directory to use for temporaries and outputs.',
                        default=None)
    result.add_argument('--verbose',
                        help='To enable verbose logging.',
                        action='store_true',
                        default=False)
    options, args = result.parse_known_args(argv)
    options.quiet = not options.verbose
    # We must download the non-lib distribution when running with a specific
    # version, since BenchmarkMainEntryRunner is using R8 internals.
    # TODO(b/346477461): Look into removing this limitation.
    assert options.version is None or options.nolib
    return options, args


def main(argv, temp):
    options, args = parse_options(argv)

    if options.output:
        options.output = os.path.abspath(options.output)

    if options.temp:
        temp = options.temp
        os.makedirs(temp, exist_ok=True)

    if options.golem:
        options.no_build = True
        if options.nolib:
            print("Error: golem should always run r8lib")
            return 1

    if options.nolib:
        testBuildTargets = [
            utils.GRADLE_TASK_TEST_JAR, utils.GRADLE_TASK_TEST_DEPS_JAR,
            utils.GRADLE_TASK_TEST_UNZIP_TESTBASE
        ]
        buildTargets = [utils.GRADLE_TASK_R8, utils.GRADLE_TASK_KEEP_ANNO_JAR
                       ] + testBuildTargets
        r8jar = utils.R8_JAR
        testjars = [
            utils.R8_TESTS_JAR, utils.R8_TESTS_DEPS_JAR, utils.R8_TESTBASE_JAR
        ]
    else:
        testBuildTargets = GOLEM_BUILD_TARGETS_TESTS
        buildTargets = GOLEM_BUILD_TARGETS
        r8jar = utils.R8LIB_JAR
        testjars = [
            os.path.join(utils.R8LIB_TESTS_JAR),
            os.path.join(utils.R8LIB_TESTS_DEPS_JAR),
            os.path.join(utils.R8LIB_TESTBASE_JAR)
        ]

    if options.version or options.version_jar:
        # r8 is downloaded so only test jar needs to be built.
        buildTargets = testBuildTargets
        r8jar = options.version_jar or compiledump.download_distribution(
            options.version, options, temp)

    if not options.no_build:
        gradle.RunGradle(buildTargets + ['-Pno_internal'])

    if not options.golem:
        # When running locally, change the working directory to be in 'temp'.
        # This is hard to do properly within the JVM so we do it here.
        with utils.ChangedWorkingDirectory(temp):
            return run(options, r8jar, testjars)
    else:
        return run(options, r8jar, testjars)


def run(options, r8jar, testjars):
    jdkhome = get_jdk_home(options, options.benchmark)
    cmd = [
        jdk.GetJavaExecutable(jdkhome),
        '-Xms8g',
        '-Xmx8g',
        '-XX:+TieredCompilation',
        '-XX:TieredStopAtLevel=4',
        '-DBENCHMARK_IGNORE_CODE_SIZE_DIFFERENCES',
        f'-DBUILD_PROP_KEEPANNO_RUNTIME_PATH={utils.REPO_ROOT}/d8_r8/keepanno/build/classes/java/main',
        # Since we change the working directory to a temp folder.
        f'-DREPO_ROOT={utils.REPO_ROOT}'
    ]
    if options.enable_assertions:
        cmd.append('-ea')
    if options.print_times:
        cmd.append('-Dcom.android.tools.r8.printtimes=1')
    if not options.golem:
        cmd.extend([
            f'-DTEST_DATA_LOCATION={utils.REPO_ROOT}/d8_r8/test_modules/tests_java_8/build/classes/java/test',
            f'-DTESTBASE_DATA_LOCATION={utils.REPO_ROOT}/d8_r8/test_modules/testbase/build/classes/java/main',
        ])
    if options.iterations is not None:
        if options.iterations == 0:
            return
        cmd.append(f'-DBENCHMARK_ITERATIONS={options.iterations}')
    if options.output:
        cmd.append(f'-DBENCHMARK_OUTPUT={options.output}')
    cmd.extend(['-cp', ':'.join([r8jar] + testjars)])
    if options.debug_agent:
        cmd.append(
            '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005'
        )
    cmd.extend([
        'com.android.tools.r8.benchmarks.BenchmarkMainEntryRunner',
        options.benchmark,
        options.target,
        # When running locally the working directory is moved and we pass the
        # repository root as an argument. The runner can then setup dependencies.
        'golem' if options.golem else utils.REPO_ROOT,
    ])
    utils.PrintCmd(cmd, quiet=options.quiet)
    return subprocess.check_call(cmd)


if __name__ == '__main__':
    with utils.TempDir() as temp:
        sys.exit(main(sys.argv[1:], temp))
