#!/usr/bin/env python3

# Copyright (C) 2022 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import glob
import argparse
import pathlib
import shutil
import subprocess
import re


def sed(pattern, replacement, file):
    """ Performs an in-place string replacement of pattern in a target file

    Args:
        pattern: pattern to replace
        replacement: replacement for the pattern matches
        file: target file

    Returns:
        Nothing
    """

    with open(file) as reader:
        file_contents = reader.read()
    new_file_contents = re.sub(pattern, replacement, file_contents)
    with open(file, "w") as writer:
        writer.write(new_file_contents)


def single(items):
    """ Returns the only item from a list of just one item

    Raises a ValueError if the list does not contain exactly one element

    Args:
        items: a list of one item

    Returns:
        The only item from a single-item-list
    """

    if len(items) != 1:
        raise ValueError('Expected a list of size 1. Found: %s' % items)
    return items[0]


def update_tracing_perfetto(old_version, new_version, core_path, force_unstripped_binaries=False):
    """Updates tracing-perfetto version and artifacts (including building new binaries)

    Args:
        old_version: old version of the existing library
        new_version: new version of the library; defaults to incrementing the old_version
        core_path: path to frameworks/support directory
        force_unstripped_binaries: flag allowing to force unstripped variant of binaries
    Returns:
        Nothing
    """

    print("Updating tracing-perfetto, this can take a while...")

    # update version in code
    sed('tracingPerfettoVersion = "%s"' % old_version,
        'tracingPerfettoVersion = "%s"' % new_version,
        os.path.join(core_path, 'benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/'
                                'macro/perfetto/PerfettoSdkHandshakeTest.kt'))
    sed('TRACING_PERFETTO = "%s"' % old_version,
        'TRACING_PERFETTO = "%s"' % new_version,
        os.path.join(core_path, 'libraryversions.toml'))
    sed('#define VERSION "%s"' % old_version,
        '#define VERSION "%s"' % new_version,
        os.path.join(core_path, 'tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc'))
    sed('const val libraryVersion = "%s"' % old_version,
        'const val libraryVersion = "%s"' % new_version,
        os.path.join(core_path, 'tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/'
                                'perfetto/jni/test/PerfettoNativeTest.kt'))
    sed('const val version = "%s"' % old_version,
        'const val version = "%s"' % new_version,
        os.path.join(core_path, 'tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/'
                                'jni/PerfettoNative.kt'))

    # build new binaries
    subprocess.check_call(["./gradlew",
                           ":tracing:tracing-perfetto-binary:createProjectZip",
                           "-Pandroidx.constraints=true",
                           "-DTRACING_PERFETTO_REUSE_PREBUILTS_AAR=false"],
                          cwd=core_path)

    # copy binaries to prebuilts
    project_zip_dir = os.path.join(core_path, '../../out/dist/per-project-zips')
    project_zip_file = os.path.join(
        project_zip_dir,
        single(glob.glob('%s/*tracing*perfetto*binary*%s*.zip' % (project_zip_dir, new_version))))
    dst_dir = pathlib.Path(os.path.join(
        core_path,
        "../../prebuilts/androidx/internal/androidx/tracing/tracing-perfetto-binary",
        new_version))
    if dst_dir.exists():
        shutil.rmtree(dst_dir)
    dst_dir.mkdir()
    subprocess.check_call(
        ["unzip", "-xjqq", project_zip_file, '**/%s/**' % new_version, "-d", dst_dir])

    # force unstripped binaries if the flag is enabled
    if force_unstripped_binaries:
        # locate unstripped binaries
        out_dir = pathlib.Path(core_path, "../../out")
        arm64_lib_file = out_dir.joinpath(single(subprocess.check_output(
            'find . -type f -name "libtracing_perfetto.so"'
            ' -and -path "*RelWithDebInfo/*/obj/arm64*"'
            ' -exec stat -c "%Y %n" {} \\; |'
            ' sort | tail -1 | cut -d " " -f2-',
            cwd=out_dir,
            shell=True).splitlines()).decode())
        base_dir = arm64_lib_file.parent.parent.parent
        obj_dir = base_dir.joinpath('obj')
        if not obj_dir.exists():
            raise RuntimeError('Expected path %s to exist' % repr(obj_dir))
        jni_dir = base_dir.joinpath('jni')

        # prepare a jni folder to inject into the destination aar
        if jni_dir.exists():
            shutil.rmtree(jni_dir)
        shutil.copytree(obj_dir, jni_dir)

        # inject the jni folder into the aar
        dst_aar = os.path.join(dst_dir, 'tracing-perfetto-binary-%s.aar' % new_version)
        subprocess.check_call(['zip', '-r', dst_aar, 'jni'], cwd=base_dir)

        # clean up
        if jni_dir.exists():
            shutil.rmtree(jni_dir)

    # update SHA
    for arch in ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']:
        checksum = subprocess.check_output(
            'unzip -cxqq "*tracing*binary*%s*.aar" "**/%s/libtracing_perfetto.so" | shasum -a256 |'
            ' awk \'{print $1}\' | tr -d "\n"' % (new_version, arch),
            cwd=dst_dir,
            shell=True
        ).decode()
        if not re.fullmatch('^[0-9a-z]{64}$', checksum):
            raise ValueError('Expecting a sha256 sum. Got: %s' % checksum)
        sed(
            '"%s" to "[0-9a-z]{64}"' % arch,
            '"%s" to "%s"' % (arch, checksum),
            os.path.join(core_path, 'tracing/tracing-perfetto/src/main/java/androidx/tracing/'
                                    'perfetto/jni/PerfettoNative.kt'))

    print("Updated tracing-perfetto.")


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Updates tracing-perfetto in the source code, which involves:'
                    ' 1) updating hardcoded version references in code'
                    ' 2) building binaries and updating them in the prebuilts folder'
                    ' 3) updating SHA checksums hardcoded in code.')
    parser.add_argument('-f', '--frameworks-support-dir',
                        required=True,
                        help='Path to frameworks/support directory')
    parser.add_argument('-c', '--current-version',
                        required=True,
                        help='Current version, e.g. 1.0.0-alpha07')
    parser.add_argument('-t', '--target-version',
                        required=True,
                        help='Target version, e.g. 1.0.0-alpha08')
    parser.add_argument('-k', '--keep-binary-debug-symbols',
                        required=False,
                        default=False,
                        action='store_true',
                        help='Keeps debug symbols in the built binaries. Useful when profiling '
                             'performance of the library. ')
    args = parser.parse_args()
    core_path_abs = pathlib.Path(args.frameworks_support_dir).resolve()
    update_tracing_perfetto(args.current_version, args.target_version, core_path_abs,
                            args.keep_binary_debug_symbols)
