# Copyright (c) 2018, 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 time
import subprocess
from threading import Timer

import gradle
import jdk
import utils


def run(tool,
        args,
        build=None,
        disable_assertions=False,
        profile=False,
        track_memory_file=None,
        extra_args=None,
        stderr=None,
        stdout=None,
        return_stdout=False,
        timeout=0,
        quiet=False,
        cmd_prefix=None,
        jar=None,
        main=None,
        time_consumer=None,
        debug_agent=None,
        worker_id=None):
    cmd = []
    if cmd_prefix:
        cmd.extend(cmd_prefix)
    if build is None:
        build, args = extract_build_from_args(args)
    if build:
        gradle.run_gradle([
            utils.GRADLE_TASK_R8LIB
            if tool.startswith('r8lib') else utils.GRADLE_TASK_R8
        ])
    if track_memory_file:
        cmd.extend(['tools/track_memory.sh', track_memory_file])
    cmd.append(jdk.GetJavaExecutable(jdk.GetDefaultJdkHome()))
    if extra_args:
        cmd.extend(extra_args)
    if debug_agent is None:
        debug_agent, args = extract_debug_agent_from_args(args)
    if debug_agent:
        cmd.append(
            '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005'
        )
    if not disable_assertions:
        cmd.append('-ea')
    if profile:
        cmd.append('-agentlib:hprof=cpu=samples,interval=1,depth=8')
    if jar:
        cmd.extend(['-cp', jar, main])
    elif tool == 'r8lib-d8':
        cmd.extend(['-cp', utils.R8LIB_JAR, 'com.android.tools.r8.D8'])
    elif tool == 'r8lib-l8':
        cmd.extend(['-cp', utils.R8LIB_JAR, 'com.android.tools.r8.L8'])
    elif tool == 'r8lib-r8':
        cmd.extend(['-cp', utils.R8LIB_JAR, 'com.android.tools.r8.R8'])
    elif tool == 'r8lib-tracereferences':
        cmd.extend([
            '-cp', utils.R8LIB_JAR,
            'com.android.tools.r8.tracereferences.TraceReferences'
        ])
    else:
        cmd.extend(
            ['-cp', utils.R8_JAR, 'com.android.tools.r8.SwissArmyKnife', tool])
    lib, args = extract_lib_from_args(args)
    if lib:
        cmd.extend(["--lib", lib])
    cmd.extend(args)
    utils.PrintCmd(cmd, quiet=quiet, worker_id=worker_id)
    start = time.time()
    if timeout > 0:
        kill = lambda process: process.kill()
        proc = subprocess.Popen(cmd,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        timer = Timer(timeout, kill, [proc])
        try:
            timer.start()
            stdout, stderr = proc.communicate()
        finally:
            timer.cancel()
        result = stdout.decode('utf-8') if return_stdout else proc.returncode
    else:
        result = (subprocess.check_output(cmd).decode('utf-8') if return_stdout
                  else subprocess.call(cmd, stdout=stdout, stderr=stderr))
    duration = int((time.time() - start) * 1000)
    if time_consumer:
        time_consumer(duration)
    return result


def extract_build_from_args(input_args):
    build = True
    args = []
    for arg in input_args:
        if arg in ("--build", "--no-build"):
            build = arg == "--build"
        else:
            args.append(arg)
    return build, args


def extract_lib_from_args(input_args):
    lib = None
    args = []
    for arg in input_args:
        if arg == '--lib-android':
            lib = utils.get_android_jar(28, 0)
        elif arg == '--lib-java':
            lib = utils.RT_JAR
        else:
            args.append(arg)
    return lib, args


def extract_debug_agent_from_args(input_args):
    agent = False
    args = []
    for arg in input_args:
        if arg in ('--debug-agent', '--debug_agent'):
            agent = True
        else:
            args.append(arg)
    return agent, args
