// 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 java.net.URI
import java.nio.file.Paths
import java.nio.file.Files.readString
import net.ltgt.gradle.errorprone.errorprone
import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.spdx.sbom.gradle.SpdxSbomTask
import org.spdx.sbom.gradle.extensions.DefaultSpdxSbomTaskExtension

import com.google.gson.Gson
import java.util.UUID

plugins {
  `kotlin-dsl`
  id("dependencies-plugin")
  id("net.ltgt.errorprone") version "3.0.1"
  id("org.spdx.sbom") version "0.4.0"
}

java {
  sourceSets.main.configure {
    java.srcDir(getRoot().resolveAll("src", "main", "java"))
    resources.srcDirs(getRoot().resolveAll("third_party", "api_database", "api_database"))
  }
  sourceCompatibility = JvmCompatibility.sourceCompatibility
  targetCompatibility = JvmCompatibility.targetCompatibility
  toolchain {
    languageVersion = JavaLanguageVersion.of(JvmCompatibility.release)
  }
  withSourcesJar()
}

dependencies {
  implementation(":keepanno")
  implementation(":resourceshrinker")
  compileOnly(Deps.asm)
  implementation(":assistant")
  compileOnly(Deps.asmCommons)
  compileOnly(Deps.asmUtil)
  compileOnly(Deps.fastUtil)
  compileOnly(Deps.gson)
  compileOnly(Deps.guava)
  compileOnly(Deps.kotlinMetadata)
  compileOnly(Deps.protobuf)
  errorprone(Deps.errorprone)
}

if (project.hasProperty("spdxVersion")) {
  project.version = project.property("spdxVersion")!!
}

spdxSbom {
  targets {
    create("r8") {
      // Use of both compileClasspath and runtimeClasspath due to how the
      // dependencies jar is built and dependencies above therefore use
      // compileOnly for actual runtime dependencies.
      configurations.set(listOf("compileClasspath", "runtimeClasspath"))
      scm {
        uri.set("https://r8.googlesource.com/r8/")
        if (project.hasProperty("spdxRevision")) {
          revision.set(project.property("spdxRevision").toString())
        }
      }
      document {
        name.set("R8 Compiler Suite")
        // Generate version 5 UUID from fixed namespace UUID and name generated from revision
        // (git hash) and artifact name.
        if (project.hasProperty("spdxRevision")) {
          namespace.set(
            "https://spdx.google/"
              + uuid5(
              UUID.fromString("df17ea25-709b-4edc-8dc1-d3ca82c74e8e"),
              project.property("spdxRevision").toString() + "-r8"
            )
          )
        }
        creator.set("Organization: Google LLC")
        packageSupplier.set("Organization: Google LLC")
      }
    }
  }
}

val assistantJarTask = projectTask("assistant", "jar")
val keepAnnoJarTask = projectTask("keepanno", "jar")
val resourceShrinkerJarTask = projectTask("resourceshrinker", "jar")
val resourceShrinkerDepsTask = projectTask("resourceshrinker", "depsJar")

fun mainJarDependencies() : FileCollection {
  return sourceSets
    .main
    .get()
    .compileClasspath
    .filter({ "$it".contains("third_party")
              && "$it".contains("dependencies")
              && !"$it".contains("errorprone")
    })
}

tasks {
  withType<Exec> {
    doFirst {
      println("Executing command: ${commandLine.joinToString(" ")}")
    }
  }

  withType<ProcessResources> {
    dependsOn(gradle.includedBuild("shared").task(":downloadDeps"))
  }

  withType<SpdxSbomTask> {
    taskExtension.set(object : DefaultSpdxSbomTaskExtension() {
      override fun mapRepoUri(input: URI?, moduleId: ModuleVersionIdentifier): URI? {

        // Locate the file origin.json with URL for download location.
        fun getOriginJson() : java.nio.file.Path {
          var repositoryDir =
              moduleId.group.replace('.', '/') + "/" + moduleId.name + "/" + moduleId.version
          return Paths.get("third_party", "dependencies", repositoryDir, "origin.json");
        }

        // Simple data model of the content of origin.json generated by the tool to download
        // and create a local repository. E.g.:
        /*
            {
              "artifacts": [
                {
                  "file": "org/ow2/asm/asm/9.5/asm-9.5.pom",
                  "repo": "https://repo1.maven.org/maven2/",
                  "artifact": "org.ow2.asm:asm:pom:9.5"
                },
                {
                  "file": "org/ow2/asm/asm/9.5/asm-9.5.jar",
                  "repo": "https://repo1.maven.org/maven2/",
                  "artifact": "org.ow2.asm:asm:jar:9.5"
                }
              ]
            }
        */
        data class Artifact(val file: String, val repo: String, val artifact: String)
        data class Artifacts(val artifacts: List<Artifact>)

        // Read origin.json.
        val json = readString(getOriginJson());
        val artifacts = Gson().fromJson(json, Artifacts::class.java);
        return URI.create(artifacts.artifacts.get(0).repo)
      }
    })
  }

  val consolidatedLicense by registering {
    dependsOn(gradle.includedBuild("shared").task(":downloadDeps"))
    val root = getRoot()
    val r8License = root.resolve("LICENSE")
    val libraryLicense = root.resolve("LIBRARY-LICENSE")
    val libraryLicenseFiles = fileTree(root.resolve("library-licensing"))
    inputs.files(
      listOf(r8License, libraryLicense),
      libraryLicenseFiles,
      mainJarDependencies().map(::zipTree))

    val license = getRoot().resolveAll("build", "generatedLicense", "LICENSE")
    outputs.files(license)
    val dependencies = mutableListOf<String>()
    configurations
      .findByName("runtimeClasspath")!!
      .resolvedConfiguration
      .resolvedArtifacts
      .forEach {
        val identifier = it.id.componentIdentifier
        if (identifier is ModuleComponentIdentifier) {
          dependencies.add("${identifier.group}:${identifier.module}")
        }
      }

    doLast {
      val libraryLicenses = libraryLicense.readText()
      dependencies.forEach {
        if (!libraryLicenses.contains("- artifact: $it")) {
          throw GradleException("No license for $it in LIBRARY_LICENSE")
        }
      }
      license.getParentFile().mkdirs()
      license.createNewFile()
      license.writeText(buildString {
        append("This file lists all licenses for code distributed.\n")
        .append("All non-library code has the following 3-Clause BSD license.\n")
        .append("\n")
        .append("\n")
        .append(r8License.readText())
        .append("\n")
        .append("\n")
        .append("Summary of distributed libraries:\n")
        .append("\n")
        .append(libraryLicenses)
        .append("\n")
        .append("\n")
        .append("Licenses details:\n")
        libraryLicenseFiles.sorted().forEach { file ->
          append("\n").append("\n").append(file.readText())
        }
      })
    }
  }

  val swissArmyKnife by registering(Jar::class) {
    dependsOn(keepAnnoJarTask)
    dependsOn(assistantJarTask)
    dependsOn(resourceShrinkerJarTask)
    dependsOn(gradle.includedBuild("shared").task(":downloadDeps"))
    from(sourceSets.main.get().output)
    exclude("com/android/tools/r8/threading/providers/**")
    from(keepAnnoJarTask.outputs.files.map(::zipTree))
    from(assistantJarTask.outputs.files.map(::zipTree))
    from(resourceShrinkerJarTask.outputs.files.map(::zipTree))
    from(getRoot().resolve("LICENSE"))
    entryCompression = ZipEntryCompression.STORED
    manifest {
      attributes["Main-Class"] = "com.android.tools.r8.SwissArmyKnife"
    }
    exclude("META-INF/*.kotlin_module")
    exclude("**/*.kotlin_metadata")
    exclude("keepspec.proto")
    destinationDirectory.set(getRoot().resolveAll("build", "libs"))
    archiveFileName.set("r8-full-exclude-deps.jar")
  }

  val threadingModuleBlockingJar by registering(Zip::class) {
    from(sourceSets.main.get().output)
    include("com/android/tools/r8/threading/providers/blocking/**")
    destinationDirectory.set(getRoot().resolveAll("build", "libs"))
    archiveFileName.set("threading-module-blocking.jar")
  }

  val threadingModuleSingleThreadedJar by registering(Zip::class) {
    from(sourceSets.main.get().output)
    include("com/android/tools/r8/threading/providers/singlethreaded/**")
    destinationDirectory.set(getRoot().resolveAll("build", "libs"))
    archiveFileName.set("threading-module-single-threaded.jar")
  }

  val depsJar by registering(Zip::class) {
    dependsOn(gradle.includedBuild("shared").task(":downloadDeps"))
    dependsOn(resourceShrinkerDepsTask)
    dependsOn(threadingModuleBlockingJar)
    dependsOn(threadingModuleSingleThreadedJar)
    from(threadingModuleBlockingJar.get().outputs.getFiles().map(::zipTree))
    from(threadingModuleSingleThreadedJar.get().outputs.getFiles().map(::zipTree))
    from(mainJarDependencies().map(::zipTree))
    from(resourceShrinkerDepsTask.outputs.files.map(::zipTree))
    from(consolidatedLicense)
    exclude("**/module-info.class")
    exclude("**/*.kotlin_metadata")
    exclude("META-INF/*.kotlin_module")
    exclude("META-INF/com.android.tools/**")
    exclude("META-INF/LICENSE*")
    exclude("META-INF/MANIFEST.MF")
    exclude("META-INF/maven/**")
    exclude("META-INF/proguard/**")
    exclude("META-INF/versions/**")
    exclude("META-INF/services/kotlin.reflect.**")
    exclude("**/*.xml")
    exclude("com/android/version.properties")
    exclude("NOTICE")
    exclude("README.md")
    exclude("javax/annotation/**")
    exclude("wireless/**")
    exclude("google/protobuf/**")
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    archiveFileName.set("deps.jar")
  }


val swissArmyKnifeWithoutLicense by registering(Zip::class) {
    dependsOn(swissArmyKnife)
    from(swissArmyKnife.get().outputs.files.map(::zipTree))
    exclude("LICENSE")
    exclude("androidx/")
    exclude("androidx/annotation/")
    exclude("androidx/annotation/keep/**")
    archiveFileName.set("swiss-army-no-license.jar")
}

val r8WithRelocatedDeps by registering(Exec::class) {
    dependsOn(depsJar)
    dependsOn(swissArmyKnifeWithoutLicense)
    val swissArmy = swissArmyKnifeWithoutLicense.get().outputs.files.singleFile
    val deps = depsJar.get().outputs.files.singleFile
    inputs.files(listOf(swissArmy, deps))
    val output = getRoot().resolveAll("build", "libs", "r8.jar")
    outputs.file(output)
    commandLine = baseCompilerCommandLine(
      swissArmy,
      deps,
      "relocator",
      listOf("--input",
             "$swissArmy",
             "--input",
             "$deps",
             "--output",
             "$output",
             // Add identity mapping to enforce no relocation of things already in package
             // com.android.tools.r8.
             "--map",
             "com.android.tools.r8.**->com.android.tools.r8",
             // Add identify for the public annotation surface of keepanno
             "--map",
             "com.android.tools.r8.keepanno.annotations.**->com.android.tools.r8.keepanno.annotations",
             // Explicitly move all other keepanno utilities.
             "--map",
             "com.android.tools.r8.keepanno.**->com.android.tools.r8.relocated.keepanno",
             "--map",
             "com.android.**->com.android.tools.r8.com.android",
             "--map",
             "com.android.build.shrinker.**->com.android.tools.r8.resourceshrinker",
             "--map",
             "com.google.common.**->com.android.tools.r8.com.google.common",
             "--map",
             "com.google.gson.**->com.android.tools.r8.com.google.gson",
             "--map",
             "com.google.thirdparty.**->com.android.tools.r8.com.google.thirdparty",
             "--map",
             "org.objectweb.asm.**->com.android.tools.r8.org.objectweb.asm",
             "--map",
             "it.unimi.dsi.fastutil.**->com.android.tools.r8.it.unimi.dsi.fastutil",
             "--map",
             "kotlin.**->com.android.tools.r8.jetbrains.kotlin",
             "--map",
             "kotlinx.**->com.android.tools.r8.jetbrains.kotlinx",
             "--map",
             "org.jetbrains.**->com.android.tools.r8.org.jetbrains",
             "--map",
             "org.intellij.**->com.android.tools.r8.org.intellij",
             "--map",
             "org.checkerframework.**->com.android.tools.r8.org.checkerframework",
             "--map",
             "com.google.j2objc.**->com.android.tools.r8.com.google.j2objc",
             "--map",
             "com.google.protobuf.**->com.android.tools.r8.com.google.protobuf",
             "--map",
             "android.aapt.**->com.android.tools.r8.android.aapt"
      ))
  }
}

tasks.withType<KotlinCompile> {
  enabled = false
}

tasks.withType<JavaCompile> {
  dependsOn(gradle.includedBuild("shared").task(":downloadDeps"))
  println("NOTE: Running with JDK: " + org.gradle.internal.jvm.Jvm.current().javaHome)

  // Enable error prone for D8/R8 main sources.
  options.errorprone.isEnabled.set(!project.hasProperty("disable_errorprone"))

  // Make all warnings errors. Warnings that we have chosen not to fix (or suppress) are disabled
  // outright below.
  options.compilerArgs.add("-Werror")

  // Increase number of reported errors to 1000 (default is 100).
  options.compilerArgs.add("-Xmaxerrs")
  options.compilerArgs.add("1000")

  // Non-default / Experimental checks - explicitly enforced.
  options.errorprone.error("RemoveUnusedImports")
  options.errorprone.error("InconsistentOverloads")
  options.errorprone.error("MissingDefault")
  options.errorprone.error("MultipleTopLevelClasses")
  options.errorprone.error("NarrowingCompoundAssignment")

  // Warnings that cause unwanted edits (e.g., inability to write informative asserts).
  options.errorprone.disable("AlreadyChecked")

  // JavaDoc related warnings. Would be nice to resolve but of no real consequence.
  options.errorprone.disable("InvalidLink")
  options.errorprone.disable("InvalidBlockTag")
  options.errorprone.disable("InvalidInlineTag")
  options.errorprone.disable("EmptyBlockTag")
  options.errorprone.disable("MissingSummary")
  options.errorprone.disable("UnrecognisedJavadocTag")
  options.errorprone.disable("AlmostJavadoc")

  // Moving away from identity and canonical items is not planned.
  options.errorprone.disable("IdentityHashMapUsage")
}
