#!/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 orderes the repositories by name, so
# prefix with X- to control the order, as many dependencies are present
# in several repositories.
REPOSITORIES = [
    'A-Google=https://maven.google.com/',
    'B-Maven Central=https://repo1.maven.org/maven2/',
    "C-Gradle Plugins=https://plugins.gradle.org/m2/",
]

ANDRDID_SUPPORT_VERSION = '25.4.0'
ASM_VERSION = '9.5'
ESPRESSO_VERSION = '3.0.0'
FASTUTIL_VERSION = '7.2.1'
KOTLIN_METADATA_VERSION = '0.7.0'
KOTLIN_VERSION = '1.8.0'
GUAVA_VERSION = '31.1-jre'
GUAVA_VERSION_NEW = '32.1.2-jre'
GSON_VERSION = '2.10.1'
JAVASSIST_VERSION = '3.29.2-GA'
JUNIT_VERSION = '4.13-beta-2'
MOCKITO_VERSION = '2.10.0'
SMALI_VERSION = '3.0.3'
ERROR_PRONE_VERSION = '2.18.0'
TESTNG_VERSION = '6.10'

# Resource shrinker dependency versions
AAPT2_PROTO_VERSION = '8.2.0-alpha10-10154469'
PROTOBUF_VERSION = '3.19.3'
STUDIO_SDK_VERSION = '31.2.0-alpha10'

BUILD_DEPENDENCIES = [
    '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.jetbrains.kotlinx:kotlinx-metadata-jvm:{version}'.format(
        version=KOTLIN_METADATA_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),
]

TEST_DEPENDENCIES = [
    'junit:junit:{version}'.format(version=JUNIT_VERSION),
    '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.javassist:javassist:{version}'.format(version=JAVASSIST_VERSION),
    'org.jetbrains.kotlin:kotlin-stdlib:{version}'.format(
        version=KOTLIN_VERSION),
    'org.jetbrains.kotlin:kotlin-reflect:{version}'.format(
        version=KOTLIN_VERSION),
    'org.mockito:mockito-core:{version}'.format(version=MOCKITO_VERSION),
    'org.testng:testng:{version}'.format(version=TESTNG_VERSION),
]

NEW_DEPENDENCIES = [
    'com.google.guava:guava:{version}'.format(version=GUAVA_VERSION_NEW),
    'org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:4.0.6',
    'org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.10',
    'org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.8.10',
    'org.jetbrains.kotlin:kotlin-reflect:1.6.10',
    'org.jetbrains.kotlin:kotlin-reflect:1.8.10',
    'org.jetbrains.kotlin:kotlin-script-runtime:1.8.10',
    'org.jetbrains.kotlin:kotlin-tooling-core:1.8.10',
    'net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:3.0.1',
    'com.google.errorprone:javac:9+181-r4173-1',
    # Gradle 8.3
    'org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:4.1.0',
    'org.jetbrains.kotlin:kotlin-assignment-compiler-plugin-embeddable:1.9.0',
    'org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.0',
    'org.jetbrains.kotlin:kotlin-reflect:1.9.0',
    'org.jetbrains.kotlin:kotlin-script-runtime:1.9.0',
    'org.jetbrains.kotlin:kotlin-sam-with-receiver-compiler-plugin-embeddable:1.9.0',
    # Resource shrinker
    '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.google.protobuf:protobuf-java:{version}'.format(
        version=PROTOBUF_VERSION),
]


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)')
    return result.parse_args()


def main():
    args = parse_options()

    dependencies_path = os.path.join(utils.THIRD_PARTY, 'dependencies')
    print("Downloading to " + dependencies_path)
    remove_local_maven_repository(dependencies_path)
    create_local_maven_repository(args, dependencies_path, REPOSITORIES,
                                  BUILD_DEPENDENCIES + TEST_DEPENDENCIES)

    dependencies_new_path = os.path.join(utils.THIRD_PARTY, 'dependencies_new')
    print("Downloading to " + dependencies_new_path)
    remove_local_maven_repository(dependencies_new_path)
    create_local_maven_repository(args, dependencies_new_path, REPOSITORIES,
                                  NEW_DEPENDENCIES)

    print("Uploading to Google Cloud Storage:")
    with utils.ChangedWorkingDirectory(utils.THIRD_PARTY):
        for dependency in ['dependencies', 'dependencies_new']:
            cmd = [
                'upload_to_google_storage.py', '-a', '--bucket', 'r8-deps',
                dependency
            ]
            subprocess.check_call(cmd)


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