// 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.Path
import java.nio.file.Paths
import kotlin.io.path.exists
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
  withSourcesJar()
}

dependencies {
  implementation(":keepanno")
  implementation(":resourceshrinker")
  compileOnly(Deps.asm)
  compileOnly(Deps.asmCommons)
  compileOnly(Deps.asmUtil)
  compileOnly(Deps.fastUtil)
  compileOnly(Deps.gson)
  compileOnly(Deps.guava)
  compileOnly(Deps.kotlinMetadata)
  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 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(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(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")
    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/**")
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    archiveFileName.set("deps.jar")
  }


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

val r8WithRelocatedDeps by registering(Exec::class) {
    dependsOn(depsJar)
    dependsOn(swissArmyKnifeWithoutLicense)
    val swissArmy = swissArmyKnifeWithoutLicense.get().outputs.getFiles().getSingleFile()
    val deps = depsJar.get().outputs.files.getSingleFile()
    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")
}
