plugins {
    id 'java' // changes the behavior of TARGET_JVM_VERSION_ATTRIBUTE

    id "com.google.osdetector" apply false
    id "me.champeau.gradle.japicmp" apply false
    id "net.ltgt.errorprone" apply false
    id 'com.google.cloud.tools.jib' apply false
}

import net.ltgt.gradle.errorprone.CheckSeverity
import org.gradle.util.GUtil

subprojects {
    apply plugin: "checkstyle"
    apply plugin: "idea"
    apply plugin: "signing"
    apply plugin: "jacoco"

    apply plugin: "com.google.osdetector"
    apply plugin: "net.ltgt.errorprone"

    group = "io.grpc"
    version = "1.56.1-SNAPSHOT" // CURRENT_GRPC_VERSION

    repositories {
        maven { // The google mirror is less flaky than mavenCentral()
            url "https://maven-central.storage-download.googleapis.com/maven2/" }
        mavenCentral()
        mavenLocal()
    }

    tasks.withType(JavaCompile).configureEach {
        it.options.compilerArgs += [
            "-Xlint:all",
            "-Xlint:-options",
            "-Xlint:-path",
            "-Xlint:-try"
        ]
        it.options.encoding = "UTF-8"
        if (rootProject.hasProperty('failOnWarnings') && rootProject.failOnWarnings.toBoolean()) {
            it.options.compilerArgs += ["-Werror"]
        }
    }

    tasks.withType(GenerateModuleMetadata).configureEach {
        // Module metadata, introduced in Gradle 6.0, conflicts with our publishing task for
        // grpc-alts and grpc-compiler.
        enabled = false
    }

    def isAndroid = project.name in [
            'grpc-android', 'grpc-android-interop-testing', 'grpc-cronet']

    ext {
        def exeSuffix = osdetector.os == 'windows' ? ".exe" : ""
        protocPluginBaseName = 'protoc-gen-grpc-java'
        javaPluginPath = "$rootDir/compiler/build/exe/java_plugin/$protocPluginBaseName$exeSuffix"

        configureProtoCompilation = {
            String generatedSourcePath = "${projectDir}/src/generated"
            project.protobuf {
                protoc {
                    if (project.hasProperty('protoc')) {
                        path = project.protoc
                    } else {
                        artifact = libs.protobuf.protoc.get()
                    }
                }
                generateProtoTasks {
                    all().each { task ->
                        // Recompile protos when build.gradle has been changed, because
                        // it's possible the version of protoc has been changed.
                        task.inputs.file("${rootProject.projectDir}/build.gradle")
                          .withPathSensitivity(PathSensitivity.RELATIVE)
                          .withPropertyName('root build.gradle')
                        if (isAndroid) {
                            task.builtins {
                                java { option 'lite' }
                            }
                        }
                    }
                }
            }
            if (rootProject.childProjects.containsKey('grpc-compiler')) {
                // Only when the codegen is built along with the project, will we be able to run
                // the grpc code generator.
                def syncGeneratedSources = tasks.register("syncGeneratedSources") { }
                project.protobuf {
                    plugins { grpc { path = javaPluginPath } }
                    generateProtoTasks {
                        all().each { task ->
                            String variantOrSourceSet = isAndroid ? task.variant.name : task.sourceSet.name
                            def syncTask = project.tasks.register("syncGeneratedSources${variantOrSourceSet}", Sync) {
                                from task
                                into "$generatedSourcePath/$variantOrSourceSet"
                                include "grpc/"
                            }
                            syncGeneratedSources.configure {
                                dependsOn syncTask
                            }

                            task.configure {
                                dependsOn ':grpc-compiler:java_pluginExecutable'
                                // Recompile protos when the codegen has been changed
                                inputs.file javaPluginPath
                                plugins { grpc { option 'noversion' } }
                                if (isAndroid) {
                                    plugins {
                                        grpc {
                                            option 'lite'
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                // Re-sync as part of a normal build, to avoid forgetting to run the sync
                tasks.named("assemble").configure {
                    dependsOn syncGeneratedSources
                }
            } else {
                // Otherwise, we just use the checked-in generated code.
                if (isAndroid) {
                    project.android.sourceSets {
                        debug { java { srcDir "${generatedSourcePath}/debug/grpc" } }
                        release { java { srcDir "${generatedSourcePath}/release/grpc" } }
                    }
                } else {
                    project.sourceSets.each() { sourceSet ->
                        sourceSet.java { srcDir "${generatedSourcePath}/${sourceSet.name}/grpc" }
                    }
                }
            }

            tasks.withType(JavaCompile).configureEach {
                appendToProperty(
                    it.options.errorprone.excludedPaths,
                    ".*/src/generated/[^/]+/java/.*" +
                        "|.*/build/generated/source/proto/[^/]+/java/.*",
                    "|")
            }
        }

        libraries = libs

        appendToProperty = { Property<String> property, String value, String separator ->
            if (property.present) {
                property.set(property.get() + separator + value)
            } else {
                property.set(value)
            }
        }
    }

    // Disable JavaDoc doclint on Java 8. It's annoying.
    if (JavaVersion.current().isJava8Compatible()) {
        allprojects {
            tasks.withType(Javadoc).configureEach {
                options.addStringOption('Xdoclint:none', '-quiet')
            }
        }
    }

    checkstyle {
        configDirectory = file("$rootDir/buildscripts")
        toolVersion = libs.checkstyle.get().version
        ignoreFailures = false
        if (rootProject.hasProperty("checkstyle.ignoreFailures")) {
            ignoreFailures = rootProject.properties["checkstyle.ignoreFailures"].toBoolean()
        }
    }

    if (!project.hasProperty('errorProne') || errorProne.toBoolean()) {
        dependencies {
            errorprone JavaVersion.current().isJava11Compatible() ? libs.errorprone.core : libs.errorprone.corejava8
        }
    } else {
        // Disable Error Prone
        tasks.withType(JavaCompile).configureEach {
            options.errorprone.enabled = false
        }
    }

    plugins.withId("java") {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8

        dependencies {
            testImplementation libraries.junit,
                    libraries.mockito.core,
                    libraries.truth
        }

        tasks.named("compileTestJava").configure {
            // serialVersionUID is basically guaranteed to be useless in our tests
            options.compilerArgs += [
                "-Xlint:-serial"
            ]
        }

        tasks.named("jar").configure {
            manifest {
                attributes('Implementation-Title': name,
                        'Implementation-Version': project.version)
            }
        }

        tasks.named("javadoc").configure {
            options {
                encoding = 'UTF-8'
                use = true
                links 'https://docs.oracle.com/javase/8/docs/api/'
                source = "8"
            }
        }

        tasks.named("checkstyleMain").configure {
            source = fileTree(dir: "$projectDir/src/main", include: "**/*.java")
        }

        tasks.named("checkstyleTest").configure {
            source = fileTree(dir: "$projectDir/src/test", include: "**/*.java")
        }

        // At a test failure, log the stack trace to the console so that we don't
        // have to open the HTML in a browser.
        tasks.named("test").configure {
            testLogging {
                exceptionFormat = 'full'
                showExceptions true
                showCauses true
                showStackTraces true
            }
            maxHeapSize = '1500m'
        }

        if (!project.hasProperty('errorProne') || errorProne.toBoolean()) {
            dependencies {
                annotationProcessor libs.guava.betaChecker
            }
        }

        tasks.named("compileJava").configure {
            // This project targets Java 7 (no time.Duration class)
            options.errorprone.check("PreferJavaTimeOverload", CheckSeverity.OFF)
            options.errorprone.check("JavaUtilDate", CheckSeverity.OFF)
            // The warning fails to provide a source location
            options.errorprone.check("MissingSummary", CheckSeverity.OFF)
        }
        tasks.named("compileTestJava").configure {
            // LinkedList doesn't hurt much in tests and has lots of usages
            options.errorprone.check("JdkObsolete", CheckSeverity.OFF)
            options.errorprone.check("PreferJavaTimeOverload", CheckSeverity.OFF)
            options.errorprone.check("JavaUtilDate", CheckSeverity.OFF)
        }

        plugins.withId("ru.vyarus.animalsniffer") {
	    // Only available after java plugin has loaded
            animalsniffer {
                toolVersion = libs.animalsniffer.asProvider().get().version
            }
        }
    }

    plugins.withId("java-library") {
        // Detect Maven Enforcer's dependencyConvergence failures. We only care
        // for artifacts used as libraries by others with Maven.
        tasks.register('checkUpperBoundDeps') {
            inputs.files(configurations.runtimeClasspath).withNormalizer(ClasspathNormalizer)
            outputs.file("${buildDir}/tmp/${name}") // Fake output for UP-TO-DATE checking
            doLast {
                requireUpperBoundDepsMatch(configurations.runtimeClasspath, project)
            }
        }
        tasks.named('compileJava').configure {
            dependsOn checkUpperBoundDeps
        }
    }

    plugins.withId("me.champeau.jmh") {
        // invoke jmh on a single benchmark class like so:
        //   ./gradlew -PjmhIncludeSingleClass=StatsTraceContextBenchmark clean :grpc-core:jmh
	tasks.named("compileJmhJava").configure {
	    sourceCompatibility = 1.8
	    targetCompatibility = 1.8
	}
        tasks.named("jmh").configure {
            warmupIterations = 10
            iterations = 10
            fork = 1
            // None of our benchmarks need the tests, and we have pseudo-circular
            // dependencies that break when including them. (context's testCompile
            // depends on core; core's testCompile depends on testing)
            includeTests = false
            if (project.hasProperty('jmhIncludeSingleClass')) {
                includes = [
                    project.property('jmhIncludeSingleClass')
                ]
            }
        }
    }

    plugins.withId("com.github.johnrengelman.shadow") {
        tasks.named("shadowJar").configure {
            // Do a dance to remove Class-Path. This needs to run after the doFirst() from the
            // shadow plugin that adds Class-Path and before the core jar action. Using doFirst will
            // have this run before the shadow plugin, and doLast will run after the core jar
            // action. See #8606.
            // The shadow plugin adds another doFirst when application is used for setting
            // Main-Class. Ordering with it doesn't matter.
            actions.add(plugins.hasPlugin("application") ? 2 : 1, new Action<Task>() {
                @Override public void execute(Task task) {
                    if (!task.manifest.attributes.remove("Class-Path")) {
                        throw new AssertionError("Did not find Class-Path to remove from manifest")
                    }
                }
            })
        }
    }

    plugins.withId("maven-publish") {
        publishing {
            publications {
                // do not use mavenJava, as java plugin will modify it via "magic"
                maven(MavenPublication) {
                    pom {
                        name = project.group + ":" + project.name
                        url = 'https://github.com/grpc/grpc-java'
                        afterEvaluate {
                            // description is not available until evaluated.
                            description = project.description
                        }

                        scm {
                            connection = 'scm:git:https://github.com/grpc/grpc-java.git'
                            developerConnection = 'scm:git:git@github.com:grpc/grpc-java.git'
                            url = 'https://github.com/grpc/grpc-java'
                        }

                        licenses {
                            license {
                                name = 'Apache 2.0'
                                url = 'https://opensource.org/licenses/Apache-2.0'
                            }
                        }

                        developers {
                            developer {
                                id = "grpc.io"
                                name = "gRPC Contributors"
                                email = "grpc-io@googlegroups.com"
                                url = "https://grpc.io/"
                                organization = "gRPC Authors"
                                organizationUrl = "https://www.google.com"
                            }
                        }
                    }
                }
            }
            repositories {
                maven {
                    if (rootProject.hasProperty('repositoryDir')) {
                        url = new File(rootProject.repositoryDir).toURI()
                    } else {
                        String stagingUrl
                        if (rootProject.hasProperty('repositoryId')) {
                            stagingUrl = 'https://oss.sonatype.org/service/local/staging/deployByRepositoryId/' +
                                    rootProject.repositoryId
                        } else {
                            stagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
                        }
                        credentials {
                            if (rootProject.hasProperty('ossrhUsername') && rootProject.hasProperty('ossrhPassword')) {
                                username = rootProject.ossrhUsername
                                password = rootProject.ossrhPassword
                            }
                        }
                        def releaseUrl = stagingUrl
                        def snapshotUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'
                        url = version.endsWith('SNAPSHOT') ? snapshotUrl : releaseUrl
                    }
                }
            }
        }

        signing {
            required false
            sign publishing.publications.maven
        }

        plugins.withId("java") {
            java {
                withJavadocJar()
                withSourcesJar()
            }

            publishing {
                publications {
                    maven {
                        if (project.name != 'grpc-netty-shaded') {
                            from components.java
                        }
                    }
                }
            }
        }
    }

    // Run with: ./gradlew japicmp --continue
    plugins.withId("me.champeau.gradle.japicmp") {
        def baselineGrpcVersion = '1.6.1'

        // Get the baseline version's jar for this subproject
        File baselineArtifact = null
        // Use a detached configuration, otherwise the current version's jar will take precedence
        // over the baseline jar.
        // A necessary hack, the intuitive thing does NOT work:
        // https://discuss.gradle.org/t/is-the-default-configuration-leaking-into-independent-configurations/2088/6
        def oldGroup = project.group
        try {
            project.group = 'virtual_group_for_japicmp'
            String depModule = "io.grpc:${project.name}:${baselineGrpcVersion}@jar"
            String depJar = "${project.name}-${baselineGrpcVersion}.jar"
            Configuration configuration = configurations.detachedConfiguration(
                    dependencies.create(depModule)
                    )
            baselineArtifact = files(configuration.files).filter {
                it.name.equals(depJar)
            }.singleFile
        } finally {
            project.group = oldGroup
        }

        // Add a japicmp task that compares the current .jar with baseline .jar
        tasks.register("japicmp", me.champeau.gradle.japicmp.JapicmpTask) {
            dependsOn jar
            oldClasspath = files(baselineArtifact)
            newClasspath = files(jar.archiveFile)
            onlyBinaryIncompatibleModified = false
            // Be quiet about things that did not change
            onlyModified = true
            // This task should fail if there are incompatible changes
            failOnModification = true
            ignoreMissingClasses = true
            htmlOutputFile = file("$buildDir/reports/japi.html")

            packageExcludes = ['io.grpc.internal']

            // Also break on source incompatible changes, not just binary.
            // Eg adding abstract method to public class.
            // TODO(zpencer): enable after japicmp-gradle-plugin/pull/14
            // breakOnSourceIncompatibility = true

            // Ignore any classes or methods marked @ExperimentalApi
            // TODO(zpencer): enable after japicmp-gradle-plugin/pull/15
            // annotationExcludes = ['@io.grpc.ExperimentalApi']
        }
    }
}

class DepAndParents {
    DependencyResult dep
    List<String> parents
}

/**
 * Make sure that Maven would select the same versions as Gradle selected.
 * This is essentially the same as if we used Maven Enforcer's
 * requireUpperBoundDeps for our artifacts.
 */
def requireUpperBoundDepsMatch(Configuration conf, Project project) {
    // artifact name => version
    Map<String,String> golden = conf.resolvedConfiguration.resolvedArtifacts.collectEntries {
        ResolvedArtifact it ->
            ModuleVersionIdentifier id = it.moduleVersion.id
            [id.group + ":" + id.name, id.version]
    }
    // Breadth-first search like Maven for dependency resolution
    Queue<DepAndParents> queue = new ArrayDeque<>()
    conf.incoming.resolutionResult.root.dependencies.each {
        queue.add(new DepAndParents(dep: it, parents: [project.displayName]))
    }
    Set<String> found = new HashSet<>()
    while (!queue.isEmpty()) {
        DepAndParents depAndParents = queue.remove()
        ResolvedDependencyResult result = (ResolvedDependencyResult) depAndParents.dep
        ModuleVersionIdentifier id = result.selected.moduleVersion
        String artifact = id.group + ":" + id.name
        if (found.contains(artifact))
            continue
        found.add(artifact)
        String version
        if (result.requested instanceof ProjectComponentSelector) {
            ProjectComponentSelector selector = (ProjectComponentSelector) result.requested
            version = project.findProject(selector.projectPath).version
        } else {
            version = ((ModuleComponentSelector) result.requested).version
        }
        String goldenVersion = golden[artifact]
        if (goldenVersion != version && "[$goldenVersion]" != version) {
            throw new RuntimeException(
                "Maven version skew: $artifact ($version != $goldenVersion) "
                + "Bad version dependency path: " + depAndParents.parents
                + " Run './gradlew $project.path:dependencies --configuration $conf.name' "
                + "to diagnose")
        }
        result.selected.dependencies.each {
            queue.add(new DepAndParents(
                dep: it, parents: depAndParents.parents + [artifact + ":" + version]))
        }
    }
}

repositories {
    mavenCentral()
    google()
}

def isAcceptableVersion(ModuleComponentIdentifier candidate) {
    String group = candidate.group
    String module = candidate.module
    String version = candidate.version
    if (group == 'com.google.guava')
        return true
    if (group == 'io.netty' && version.contains('Final'))
        return true
    if (module == 'android-api-level-19')
        return true
    return version ==~ /^[0-9]+(\.[0-9]+)+$/
}

configurations {
    checkForUpdates {
        attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
        resolutionStrategy {
            componentSelection {
                all {
                    if (!isAcceptableVersion(it.candidate))
                        it.reject("Not stable version")
                }
            }
        }
    }
}

// Checks every dependency in the version catalog to see if there is a newer
// version available. The 'checkForUpdates' configuration restricts the
// versions considered.
tasks.register('checkForUpdates') {
    doLast {
        def updateConf = project.configurations.checkForUpdates
        updateConf.setVisible(false)
        updateConf.setTransitive(false)
        def versionCatalog = project.extensions.getByType(VersionCatalogsExtension).named("libs")
        versionCatalog.libraryAliases.each { name ->
            def dep = versionCatalog.findLibrary(name).get().get()

            def oldConf = updateConf.copy()
            def oldDep = project.dependencies.create(
                group: dep.group, name: dep.name, version: dep.versionConstraint, classifier: 'pom')
            oldConf.dependencies.add(oldDep)
            def oldResolved = oldConf.resolvedConfiguration.resolvedArtifacts.iterator().next()

            def newConf = updateConf.copy()
            def newDep = project.dependencies.create(
                group: dep.group, name: dep.name, version: '+', classifier: 'pom')
            newConf.dependencies.add(newDep)
            def newResolved = newConf.resolvedConfiguration.resolvedArtifacts.iterator().next()
            if (oldResolved != newResolved) {
                def oldId = oldResolved.id.componentIdentifier
                def newId = newResolved.id.componentIdentifier
                println("${newId.group}:${newId.module} ${oldId.version} -> ${newId.version}")
            }
        }
    }
}
