/*
 * Copyright (C) 2016 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 androidx.build.BuildOnServerKt
import androidx.build.LibraryType
import androidx.build.SupportConfig
import androidx.build.SdkHelperKt
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("AndroidXPlugin")
    id("kotlin")
    id("com.github.johnrengelman.shadow")
}

def antlrOut = "$buildDir/generated/antlr/grammar-gen/"
sourceSets {
    main.java.srcDirs += "src/main/grammar-gen"
    main.java.srcDirs += antlrOut
}

configurations {
    /**
     * shadowed is used for dependencies which we jarjar into the library jar instead of adding it
     * as a pom dependency
     */
    shadowed
    // make sure shadowed dependencies show up as compileOnly so that normal compilation works
    compileOnly.extendsFrom(shadowed)
    // compiler tests run w/o shadowed classes so we should add those dependencies into test
    // configuration
    testCompile.extendsFrom(shadowed)
    // for downstream tests, provide a configuration that includes the shadow output + other
    // dependencies that are not shadowed
    shadowAndImplementation.extendsFrom(shadow)
    shadowAndImplementation.extendsFrom(implementation)
}

shadowJar {
    // set classifier to empty string so that it doesn't append anything to the jar.
    archiveClassifier = ""
    configurations = [project.configurations.shadowed]
    dependencies {
        // antlr has dependencies on unrelated projects for its gui stuff, do not include them
        exclude(dependency("org.abego.treelayout:.*"))
        exclude(dependency("org.glassfish:.*"))
        exclude(dependency("com.ibm.icu:.*"))
    }
    relocate("org.antlr", "androidx.room.jarjarred.org.antlr")
    relocate("org.stringtemplate", "androidx.room.jarjarred.org.stringtemplate")
}

jar {
    // set a classifier on this one so that the output does not clash with the output from
    // shadowJar task. We should never use this directly as it won't have the shadowed classes that
    // are necessary to run.
    archiveClassifier = "before-jarjar"
}

configurations {
    // replace the standard jar with the one built by 'shadowJar' in both api and runtime variants
    apiElements.outgoing.artifacts.clear()
    apiElements.outgoing.artifact(shadowJar) {
        builtBy shadowJar
    }
    runtimeElements.outgoing.artifacts.clear()
    runtimeElements.outgoing.artifact(shadowJar) {
        builtBy shadowJar
    }
}

dependencies {
    implementation(project(":room:room-common"))
    implementation(project(":room:room-migration"))
    implementation(project(":room:room-compiler-processing"))
    implementation(libs.kotlinStdlib)
    implementation(libs.autoCommon)
    implementation(libs.autoValueAnnotations)
    implementation(libs.javapoet)
    implementation(libs.kspApi)
    shadowed(libs.antlr4)
    implementation(libs.sqliteJdbc)
    implementation(libs.kotlinMetadataJvm)
    implementation(libs.apacheCommonsCodec)
    implementation(libs.intellijAnnotations)
    testImplementation(libs.truth)
    testImplementation(libs.autoValue) // to access the processor in tests
    testImplementation(libs.autoServiceAnnotations)
    testImplementation(libs.autoService) // to access the processor in tests
    testImplementation(projectOrArtifact(":paging:paging-common"))
    testImplementation(project(":room:room-compiler-processing-testing"))
    testImplementation(libs.junit)
    testImplementation(libs.jsr250)
    testImplementation(libs.mockitoCore)
    testImplementation(libs.antlr4)
    testImplementation(libs.kotlinCompilerEmbeddable)
    testImplementation(fileTree(
            dir: "${SdkHelperKt.getSdkPath(project)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
            include : "android.jar"
    ))
    testImplementation(fileTree(
            dir: "${new File(project(":room:room-runtime").buildDir, "intermediates/runtime_library_classes_jar/release/")}",
            include : "*.jar"
    ))
    testImplementation(fileTree(
            dir: "${new File(project(":sqlite:sqlite").buildDir, "libJar")}",
            include : "*.jar"
    ))
    testImplementation(project(":internal-testutils-common"))
}

def generateAntlrTask = task("generateAntlrGrammar", type: GenerateAntlrGrammar) {
    sqliteFile = file("$projectDir/SQLite.g4")
    antlrClasspath = configurations.compileClasspath
    outputDirectory = file(antlrOut)
}

@CacheableTask
abstract class GenerateAntlrGrammar extends DefaultTask {
    @PathSensitive(PathSensitivity.NONE)
    @InputFile
    File sqliteFile

    @Classpath
    FileCollection antlrClasspath

    @OutputDirectory
    File outputDirectory

    @Inject
    abstract ExecOperations getExecOperations()

    @Inject
    public GenerateAntlrGrammar() {
        description("Generates Antlr Grammar used by room")
        group("build")
    }

    @TaskAction
    void generateAntlrGrammar() {
        execOperations.javaexec {
            mainClass.set("org.antlr.v4.Tool")
            classpath = antlrClasspath
            args "SQLite.g4",
                 "-visitor",
                 "-o", new File(outputDirectory, "androidx/room/parser").path,
                 "-package", "androidx.room.parser"
        }
    }
}

/**
 * Room compiler jarjars some dependencies. This task validates the published artifacts of room
 * compiler to ensure dependencies are properly jarjarred.
 */
class CheckArtifactTask extends DefaultTask {
    @InputFiles
    FileCollection artifactInputs = project.objects.fileCollection()
    @InputFile
    File pomFile
    @OutputFile
    File result = new File(project.buildDir, "checkArtifactOutput.txt")
    /**
     * Checks the publish task's artifacts to make sure the classes.jar does include jarjarred
     * antlr classes.
     */
    def validatePublishTaskOutputs() {
        if (artifactInputs.files.isEmpty()) {
            throw new GradleException("Couldn't find the classes.jar for the room-compiler " +
                    "artifact. Ensure that publish is setup properly.")
        }
        artifactInputs.forEach {
            validateJarContents(it)
        }
    }

    /**
     * Traverses the given jar file, looks for the classes that should be jarjarred and validates
     * their location.
     */
    def validateJarContents(File jarFile) {
        Boolean found = false
        ZipFile zip = new ZipFile(jarFile)
        try {
            for (Enumeration list = zip.entries(); list.hasMoreElements(); ) {
                String entry = ((ZipEntry) list.nextElement()).name
                if (!entry.endsWith(".class")) continue
                if (entry.contains("org/antlr")) {
                    found = true
                    if (!entry.contains("androidx/room/jarjarred/org/antlr")) {
                        throw new GradleException("Any Antlr class included in the Room Compiler's" +
                                " jar file should be moved into androidx/room/jarjarred.\n" +
                                "Looks like $entry has not been moved")
                    }
                }
                if (!entry.startsWith("androidx/room/")) {
                    throw new GradleException("Found a class that is not in androidx.room " +
                            "package: $entry")
                }
            }
        } finally {
            zip.close()
        }
        if (!found) {
            throw new GradleException("Couldn't find any Antlr classes in room-compiler artifact" +
                    ".\n Antlr is jarjarred into room-compiler so there should be some files")
        }
    }

    /**
     * Checks the generated pom file to ensure it does not depend on any jarjarred dependencies
     * but still depends on others.
     */
    def validatePomTaskOutputs() {
        if (!pomFile.canRead()) {
            throw new GradleException("Cannot find the pom file for room-compiler")
        }
        def pomContents = pomFile.newReader().text
        if (pomContents.contains("antlr")) {
            throw new GradleException("Room-compiler pom file should not depend on antlr.\n" +
                    "Pom Contents:\n $pomContents")
        }
        if(!pomContents.contains("<artifactId>kotlin-stdlib</artifactId>")) {
            throw new GradleException("room-compiler should depend on kotlin stdlib.\n" +
                    "Pom Contents:\n $pomContents")
        }
    }

    @TaskAction
    def validate() {
        result.write("fail\n")
        validatePublishTaskOutputs()
        validatePomTaskOutputs()
        // have a no-op output to make gradle happy w/ input/output checking.
        result.write("ok\n")
    }
}

def checkArtifactContentsTask = tasks.register("checkArtifactTask", CheckArtifactTask) {
    it.artifactInputs.from {
        ((PublishToMavenRepository) project.tasks
                .named("publishMavenPublicationToMavenRepository").get()).getPublication()
                .artifacts.matching {
            it.classifier == null
        }.collect {
            it.file
        }
    }
    def pomTask = (GenerateMavenPom) project.tasks
            .named("generatePomFileForMavenPublication").get()
    it.pomFile = pomTask.destination
    it.dependsOn("publishMavenPublicationToMavenRepository")
}

// make sure we validate published artifacts on the build server.
BuildOnServerKt.addToBuildOnServer(project, checkArtifactContentsTask)

tasks.findByName("compileKotlin").dependsOn(generateAntlrTask)
tasks.findByName("sourceJar").dependsOn(generateAntlrTask)
tasks.findByName("compileKotlin").dependsOn(":room:room-runtime:bundleLibRuntimeToJarRelease")
tasks.findByName("compileKotlin").dependsOn(":sqlite:sqlite:jarRelease")

tasks.withType(KotlinCompile).configureEach {
    kotlinOptions {
        freeCompilerArgs += [
                "-Xjvm-default=all",
                "-Xopt-in=kotlin.RequiresOptIn",
                "-Xopt-in=kotlin.contracts.ExperimentalContracts",
                "-Xopt-in=androidx.room.compiler.processing.ExperimentalProcessingApi"
        ]
    }
}

tasks.withType(Test).configureEach {
    it.systemProperty("androidx.room.compiler.processing.strict", "true")
    it.maxParallelForks(3)
}

androidx {
    name = "Android Room Compiler"
    type = LibraryType.COMPILER_PLUGIN
    mavenGroup = LibraryGroups.ROOM
    inceptionYear = "2017"
    description = "Android Room annotation processor"
}
