#!/usr/bin/env python3
# Copyright (c) 2023, 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.path
import shutil
import subprocess
import sys

import utils

# The local_maven_repository_generator orders the repositories by name, so
# prefix with X- to control the order, as many dependencies are present
# in several repositories. Save A- for additional local repository.
REPOSITORIES = [
    'B-Google=https://maven.google.com/',
    'C-Maven Central=https://repo1.maven.org/maven2/',
    "D-Gradle Plugins=https://plugins.gradle.org/m2/",
]

ANDROIDX_COLLECTION_VERSION = '1.6.0'
ANDROIDX_TRACING_VERSION = '2.0.0-alpha05'
ASM_VERSION = '9.10.1'  # When updating update tools/asmifier.py and Toolhelper as well.
FASTUTIL_VERSION = '7.2.1'
KOTLIN_METADATA_VERSION = '2.3.10'
# This version is both our kotlin compiler and Gradle's (current) kotlin compiler.
# If Gradle is upgraded, then this version might have to split into two and
# the dependencies untangled.
KOTLIN_VERSION = '2.2.21'
GUAVA_VERSION = '32.1.2-jre'
GSON_VERSION = '2.14.0'
PLAYWRIGHT_VERSION = '1.60.0'
JAVASSIST_VERSION = '3.29.2-GA'
MOCKITO_VERSION = '2.10.0'
TEST_RETRY_VERSION = '1.6.4'
SMALI_VERSION = '3.0.3'
ERROR_PRONE_VERSION = '2.18.0'
TESTNG_VERSION = '6.10'
JUNIT_JUPITER_VERSION = '5.14.3'
JUNIT_PLATFORM_VERSION = '1.14.3'
ZIPFLINGER_VERSION = '9.0.0'
DDMLIB_VERSION = '32.2.0'

# keepanno & resource shrinker dependencies
PROTOBUF_VERSION = '4.33.5'

# Resource shrinker dependency versions
AAPT2_PROTO_VERSION = '9.1.0-alpha09-14792394'
STUDIO_SDK_VERSION = '31.5.0-alpha04'

BUILD_DEPENDENCIES = [
    'androidx.collection:collection:{version}'.format(
        version=ANDROIDX_COLLECTION_VERSION),
    'androidx.tracing:tracing:{version}'.format(
        version=ANDROIDX_TRACING_VERSION),
    'androidx.tracing:tracing-desktop:{version}'.format(
        version=ANDROIDX_TRACING_VERSION),
    'androidx.tracing:tracing-wire:{version}'.format(
        version=ANDROIDX_TRACING_VERSION),
    'androidx.tracing:tracing-wire-desktop:{version}'.format(
        version=ANDROIDX_TRACING_VERSION),
    'com.google.code.gson:gson:{version}'.format(version=GSON_VERSION),
    'com.google.guava:guava:{version}'.format(version=GUAVA_VERSION),
    'it.unimi.dsi:fastutil:{version}'.format(version=FASTUTIL_VERSION),
    'org.ow2.asm:asm:{version}'.format(version=ASM_VERSION),
    'org.ow2.asm:asm-util:{version}'.format(version=ASM_VERSION),
    'org.ow2.asm:asm-commons:{version}'.format(version=ASM_VERSION),
    'com.google.errorprone:javac:9+181-r4173-1',
    'com.android.tools.build:aapt2-proto:{version}'.format(
        version=AAPT2_PROTO_VERSION),
    'com.android.tools.layoutlib:layoutlib-api:{version}'.format(
        version=STUDIO_SDK_VERSION),
    'com.android.tools:common:{version}'.format(version=STUDIO_SDK_VERSION),
    'com.android.tools:sdk-common:{version}'.format(version=STUDIO_SDK_VERSION),
    'com.android:zipflinger:{version}'.format(version=ZIPFLINGER_VERSION),
    'com.google.protobuf:protobuf-java:{version}'.format(
        version=PROTOBUF_VERSION),
    'org.jetbrains.kotlin:kotlin-assignment-compiler-plugin-embeddable:{version}'
    .format(version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-compiler-embeddable:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-gradle-plugin-api:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-gradle-plugin-idea:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-reflect:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-sam-with-receiver-compiler-plugin-embeddable:{version}'
    .format(version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-script-runtime:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:{version}'.
    format(version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-stdlib-jdk8:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-tooling-core:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-build-tools-impl:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-metadata-jvm:{version}'.format(
        version=KOTLIN_METADATA_VERSION),
    'com.android.tools.ddms:ddmlib:{version}'.format(version=DDMLIB_VERSION),
]

TEST_DEPENDENCIES = [
    'com.android.tools.smali:smali:{version}'.format(version=SMALI_VERSION),
    'com.android.tools.smali:smali-util:{version}'.format(
        version=SMALI_VERSION),
    'com.google.errorprone:error_prone_core:{version}'.format(
        version=ERROR_PRONE_VERSION),
    'org.gradle:test-retry-gradle-plugin:{version}'.format(
        version=TEST_RETRY_VERSION),
    'org.javassist:javassist:{version}'.format(version=JAVASSIST_VERSION),
    'org.mockito:mockito-core:{version}'.format(version=MOCKITO_VERSION),
    'org.testng:testng:{version}'.format(version=TESTNG_VERSION),
    'org.junit.jupiter:junit-jupiter:{version}'.format(
        version=JUNIT_JUPITER_VERSION),
    'org.junit.vintage:junit-vintage-engine:{version}'.format(
        version=JUNIT_JUPITER_VERSION),
    'org.junit.platform:junit-platform-launcher:{version}'.format(
        version=JUNIT_PLATFORM_VERSION),
    'com.microsoft.playwright:playwright:{version}'.format(
        version=PLAYWRIGHT_VERSION),
]

PLUGIN_DEPENDENCIES = [
    'org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:pom:{version}'
    .format(version=KOTLIN_VERSION),
    'com.google.protobuf:protobuf-gradle-plugin:0.9.4',
    'org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:pom:6.4.2',
    'org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.10',
    'net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:pom:3.0.1',
    'org.spdx.sbom:org.spdx.sbom.gradle.plugin:pom:0.4.0',
    # See https://github.com/FasterXML/jackson-core/issues/999.
    'ch.randelshofer:fastdoubleparser:0.8.0',
]


def dependencies_tar(dependencies_path):
    return os.path.join(os.path.dirname(dependencies_path),
                        os.path.basename(dependencies_path) + '.tar.gz')


def dependencies_tar_sha1(dependencies_path):
    return os.path.join(os.path.dirname(dependencies_path),
                        os.path.basename(dependencies_path) + '.tar.gz.sha1')


def remove_local_maven_repository(dependencies_path):
    if os.path.exists(dependencies_path):
        shutil.rmtree(dependencies_path)
    tar = dependencies_tar(dependencies_path)
    if os.path.exists(tar):
        os.remove(tar)
    sha1 = dependencies_tar_sha1(dependencies_path)
    if os.path.exists(sha1):
        os.remove(sha1)


def create_local_maven_repository(args, dependencies_path, repositories,
                                  dependencies):
    with utils.ChangedWorkingDirectory(args.studio):
        cmd = [
            os.path.join('tools', 'base', 'bazel', 'bazel'), 'run',
            '//tools/base/bazel:local_maven_repository_generator_cli', '--',
            '--repo-path', dependencies_path, '--fetch'
        ]
        for repository in repositories:
            cmd.extend(['--remote-repo', repository])
        for dependency in dependencies:
            cmd.append(dependency)
        subprocess.check_call(cmd)


def parse_options():
    result = argparse.ArgumentParser(
        description='Create local Maven repository woth dependencies')
    result.add_argument(
        '--studio',
        metavar=('<path>'),
        required=True,
        help='Path to a studio-main checkout (to get the tool '
        '//tools/base/bazel:local_maven_repository_generator_cli)')
    result.add_argument('--plugin-deps',
                        '--plugin_deps',
                        default=False,
                        action='store_true',
                        help='Build repository Gradle plugin dependncies')
    result.add_argument(
        '--include-maven-local',
        '--include_maven_local',
        metavar=('<path>'),
        default=False,
        help='Path to maven local repository to include as dependency source')
    result.add_argument('--no-upload',
                        '--no_upload',
                        default=False,
                        action='store_true',
                        help="Don't upload to Google CLoud Storage")
    return result.parse_args()


def set_utime(path):
    os.utime(path, (0, 0))
    for root, dirs, files in os.walk(path):
        for f in files:
            os.utime(os.path.join(root, f), (0, 0))
        for d in dirs:
            os.utime(os.path.join(root, d), (0, 0))


def main():
    args = parse_options()

    repositories = REPOSITORIES
    if args.include_maven_local:
        # Add the local repository as the first for it to take precedence.
        # Use A- prefix as current local_maven_repository_generator orderes by name.
        repositories = ['A-Local=file://%s' % args.include_maven_local
                       ] + REPOSITORIES

    dependencies = []

    if args.plugin_deps:
        dependencies_plugin_path = os.path.join(utils.THIRD_PARTY,
                                                'dependencies_plugin')
        remove_local_maven_repository(dependencies_plugin_path)
        print("Downloading to " + dependencies_plugin_path)
        create_local_maven_repository(args, dependencies_plugin_path,
                                      repositories, PLUGIN_DEPENDENCIES)
        set_utime(dependencies_plugin_path)
        dependencies.append('dependencies_plugin')
    else:
        dependencies_path = os.path.join(utils.THIRD_PARTY, 'dependencies')
        remove_local_maven_repository(dependencies_path)
        print("Downloading to " + dependencies_path)
        create_local_maven_repository(args, dependencies_path, repositories,
                                      BUILD_DEPENDENCIES + TEST_DEPENDENCIES)
        set_utime(dependencies_path)
        dependencies.append('dependencies')

    upload_cmds = []
    for dependency in dependencies:
        upload_cmds.append([
            'upload_to_google_storage.py', '-a', '--bucket', 'r8-deps',
            dependency
        ])

    if not args.no_upload:
        print("Uploading to Google Cloud Storage:")
        with utils.ChangedWorkingDirectory(utils.THIRD_PARTY):
            for cmd in upload_cmds:
                subprocess.check_call(cmd)
    else:
        print("Not uploading to Google Cloud Storage. " +
              "Run the following commands in %s to do so manually" %
              utils.THIRD_PARTY)
        for cmd in upload_cmds:
            print(" ".join(cmd))


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