#!/usr/bin/env python3
# Copyright (c) 2019, 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.

from os import path

import argparse
import os
import subprocess
import sys

import jdk
import utils


def parse_arguments():
    parser = argparse.ArgumentParser(
        description='R8lib wrapper for retrace tool.')
    parser.add_argument('-c',
                        '--commit-hash',
                        '--commit_hash',
                        help='Commit hash to download r8lib map file for.',
                        default=None)
    parser.add_argument('--version',
                        help='Version to download r8lib map file for.',
                        default=None)
    parser.add_argument('--tag',
                        help='Tag to download r8lib map file for.',
                        default=None)
    parser.add_argument(
        '--exclude-deps',
        '--exclude_deps',
        default=None,
        action='store_true',
        help='Use the exclude-deps version of the mapping file.')
    parser.add_argument('--map', help='Path to r8lib map.', default=None)
    parser.add_argument('--r8jar', help='Path to r8 jar.', default=None)
    parser.add_argument('--no-r8lib',
                        '--no_r8lib',
                        default=False,
                        action='store_true',
                        help='Use r8.jar and not r8lib.jar.')
    parser.add_argument(
        '--stacktrace',
        help='Path to stacktrace file (read from stdin if not passed).',
        default=None)
    parser.add_argument('--quiet',
                        default=None,
                        action='store_true',
                        help='Disables diagnostics printing to stdout.')
    parser.add_argument(
        '--debug-agent',
        '--debug_agent',
        default=None,
        action='store_true',
        help='Attach a debug-agent to the retracer java process.')
    parser.add_argument(
        '--regex',
        default=None,
        help='Sets a custom regular expression used for parsing')
    parser.add_argument('--verbose',
                        default=None,
                        action='store_true',
                        help='Enables verbose retracing.')
    parser.add_argument('--disable-map-validation',
                        default=None,
                        action='store_true',
                        help='Disable validation of map hash.')
    return parser.parse_args()


def get_map_file(args, temp):
    # default to using the specified map file.
    if args.map:
        return args.map

    # next try to extract it from the tag/version options.
    map_path = utils.find_cloud_storage_file_from_options('r8lib.jar.map', args)
    if map_path:
        return map_path

    # next try to extract it from the stack-trace source-file content.
    if not args.stacktrace:
        if not args.quiet:
            print('Waiting for stack-trace input...')
        args.stacktrace = os.path.join(temp, 'stacktrace.txt')
        open(args.stacktrace, 'w').writelines(sys.stdin.readlines())

    r8_source_file = None
    for line in open(args.stacktrace, 'r'):
        start = line.rfind("(R8_")
        if start > 0:
            end = line.find(":", start)
            content = line[start + 1:end]
            if r8_source_file:
                if content != r8_source_file:
                    print(
                        'WARNING: there are multiple distinct R8 source files:')
                    print(' ' + r8_source_file)
                    print(' ' + content)
            else:
                r8_source_file = content

    if r8_source_file:
        (header, r8_version_or_hash, maphash) = r8_source_file.split('_')
        # If the command-line specified --exclude-deps then assume it is as previous
        # versions will not be marked as such in the source-file line.
        is_excldeps = args.exclude_deps
        excldeps_start = r8_version_or_hash.find('+excldeps')
        if (excldeps_start > 0):
            is_excldeps = True
            r8_version_or_hash = r8_version_or_hash[0:excldeps_start]
        if len(r8_version_or_hash) < 40:
            args.version = r8_version_or_hash
        else:
            args.commit_hash = r8_version_or_hash
        map_path = None
        if path.exists(utils.R8LIB_MAP) and get_hash_from_map_file(
                utils.R8LIB_MAP) == maphash:
            return utils.R8LIB_MAP

        try:
            map_path = utils.find_cloud_storage_file_from_options(
                'r8lib' + ('-exclude-deps' if is_excldeps else '') + '.jar.map',
                args)
        except Exception as e:
            print(e)
            print('WARNING: Falling back to using local mapping file.')

        if map_path and not args.disable_map_validation:
            check_maphash(map_path, maphash, args)
            return map_path

    # If no other map file was found, use the local mapping file.
    if args.r8jar:
        return args.r8jar + ".map"
    return utils.R8LIB_MAP


def check_maphash(mapping_path, maphash, args):
    infile_maphash = get_hash_from_map_file(mapping_path)
    if infile_maphash != maphash:
        print('ERROR: The mapping file hash does not match the R8 line')
        print('  In mapping file: ' + infile_maphash)
        print('  In source file:  ' + maphash)
        if (not args.exclude_deps):
            print(
                'If this could be a version without internalized dependencies '
                + 'try passing --exclude-deps')
        sys.exit(1)


def get_hash_from_map_file(mapping_path):
    map_hash_header = "# pg_map_hash: SHA-256 "
    for line in open(mapping_path, 'r'):
        if line.startswith(map_hash_header):
            return line[len(map_hash_header):].strip()


def main():
    args = parse_arguments()
    with utils.TempDir() as temp:
        map_path = get_map_file(args, temp)
        return run(map_path,
                   args.stacktrace,
                   args.r8jar,
                   args.no_r8lib,
                   quiet=args.quiet,
                   debug=args.debug_agent,
                   regex=args.regex,
                   verbose=args.verbose)


def run(map_path,
        stacktrace,
        r8jar,
        no_r8lib,
        quiet=False,
        debug=False,
        regex=None,
        verbose=False):
    retrace_args = [jdk.GetJavaExecutable()]

    if debug:
        retrace_args.append(
            '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005'
        )

    if not r8jar:
        r8jar = utils.R8_JAR if no_r8lib else utils.R8LIB_JAR

    retrace_args += [
        '-cp', r8jar, 'com.android.tools.r8.retrace.Retrace', map_path
    ]

    if regex:
        retrace_args.append('--regex')
        retrace_args.append(regex)

    if quiet:
        retrace_args.append('--quiet')

    if stacktrace:
        retrace_args.append(stacktrace)

    if verbose:
        retrace_args.append('--verbose')

    utils.PrintCmd(retrace_args, quiet=quiet)
    return subprocess.call(retrace_args)


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