/*
 * 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, "libJar")}",
            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:jarRelease")
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")
}

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