#!/usr/bin/env python3
# Copyright (c) 2016, 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.
"""
Wrapper script for running gradle.
Will make sure we pulled down gradle before running, and will use the pulled
down version to have a consistent developer experience.
"""

import argparse
import os
import subprocess
import sys

import jdk
import utils

GRADLE8_DIR = os.path.join(utils.THIRD_PARTY, 'gradle')


def get_gradle_dir():
    return os.path.join(utils.THIRD_PARTY, 'gradle')


def get_gradle_executable():
    if utils.IsWindows():
        return os.path.join(get_gradle_dir(), 'bin', 'gradle.bat')
    else:
        return os.path.join(get_gradle_dir(), 'bin', 'gradle')


def parse_options():
    parser = argparse.ArgumentParser(description='Call gradle.')
    parser.add_argument('--exclude-deps',
                        '--exclude_deps',
                        help='Build without internalized dependencies.',
                        default=False,
                        action='store_true')
    parser.add_argument(
        '--no-internal',
        '--no_internal',
        help='Do not build with support for Google internal tests.',
        default=False,
        action='store_true')
    parser.add_argument('--java-home',
                        '--java_home',
                        help='Use a custom java version to run gradle.')
    parser.add_argument('--worktree',
                        help='Gradle is running in a worktree and may lock up '
                        'the gradle caches.',
                        action='store_true',
                        default=False)
    parser.add_argument('--quiet',
                        '-q',
                        help='Only print warnings and errors from gradle.',
                        action='store_true',
                        default=False)
    return parser.parse_known_args()


def get_java_env(env):
    java_env = dict(env if env else os.environ,
                    JAVA_HOME=jdk.GetDefaultJdkHome())
    java_env['PATH'] = java_env['PATH'] + os.pathsep + os.path.join(
        jdk.GetDefaultJdkHome(), 'bin')
    java_env['GRADLE_OPTS'] = '-Xmx1g'
    return java_env


def print_cmd(s):
    if type(s) is list:
        s = ' '.join(s)
    print('Running: %s' % s)
    sys.stdout.flush()


def ensure_gradle():
    utils.ensure_google_download(GRADLE8_DIR)


def ensure_gradle_repositories():
    dependencies_dir = os.path.join(utils.THIRD_PARTY, 'dependencies')
    utils.ensure_google_download(dependencies_dir)
    dependencies_plugin_dir = os.path.join(utils.THIRD_PARTY,
                                           'dependencies_plugin')
    utils.ensure_google_download(dependencies_plugin_dir)


def ensure_jdk():
    # Gradle in the new setup will use the jdks in the evaluation - fetch
    # all beforehand.
    for root in jdk.GetAllJdkDirs():
        utils.ensure_google_download(root)


def ensure_deps():
    ensure_gradle()
    ensure_gradle_repositories()
    ensure_jdk()


def run_gradle_in(gradle_cmd,
                  args,
                  cwd,
                  throw_on_failure=True,
                  env=None,
                  quiet=False):
    ensure_deps()
    cmd = [gradle_cmd]
    # Changes to these flags should be copied to gradle_benchmark.scenarios.
    args.extend(['--offline'])
    if not any(
            arg.startswith('-Porg.gradle.java.installations.paths=')
            for arg in args):
        args.append('-Porg.gradle.java.installations.paths=' +
                    get_java_installations_paths())
    if not any(
            arg.startswith('-Porg.gradle.java.installations.auto-detect=')
            for arg in args):
        args.append('-Porg.gradle.java.installations.auto-detect=false')
    if not any(
            arg.startswith('-Porg.gradle.java.installations.auto-download=')
            for arg in args):
        args.append('-Porg.gradle.java.installations.auto-download=false')
    if quiet:
        args.append('--quiet')
    cmd.extend(args)
    with utils.ChangedWorkingDirectory(cwd):
        if not quiet:
            utils.PrintCmd(cmd)
        return_value = subprocess.call(cmd, env=get_java_env(env))
        utils.GRADLE_STOPPED = False
        if throw_on_failure and return_value != 0:
            raise Exception('Failed to execute gradle')
        return return_value


def run_gradle(args, throw_on_failure=True, env=None, quiet=False):
    return run_gradle_in(get_gradle_executable(),
                         args,
                         utils.REPO_ROOT,
                         throw_on_failure,
                         env=env,
                         quiet=quiet)


def get_java_installations_paths():
    paths = []
    openjdk_dir = os.path.join(utils.THIRD_PARTY, 'openjdk')
    if os.path.exists(openjdk_dir):
        for jdk in os.listdir(openjdk_dir):
            jdk_dir = os.path.join(openjdk_dir, jdk)
            if not os.path.isdir(jdk_dir):
                continue
            for platform in ['linux', 'osx', 'windows']:
                platform_dir = os.path.join(jdk_dir, platform)
                if os.path.exists(platform_dir):
                    paths.append(platform_dir)
    return ','.join(paths)


def main():
    (options, args) = parse_options()
    if options.java_home:
        args.append('-Dorg.gradle.java.home=' + options.java_home)
    if options.no_internal:
        args.append('-Pno_internal')
    if options.exclude_deps:
        args.append('-Pexclude_deps')
    if options.worktree:
        args.append('-g=' + os.path.join(utils.REPO_ROOT, ".gradle_user_home"))
    return run_gradle(args, quiet=options.quiet)


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