import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
  id("com.gradleup.shadow")
}

apply from: "$rootDir/gradle/shadow.gradle"

def relocatePackages = ext.relocatePackages

configurations {
  // this configuration collects libs that will be placed in the bootstrap classloader
  bootstrapLibs {
    canBeResolved = true
    canBeConsumed = false
  }
  // this configuration collects libs that will be placed in the agent classloader, isolated from the instrumented application code
  javaagentLibs {
    canBeResolved = true
    canBeConsumed = false
  }
  // this configuration stores the upstream agent dep that's extended by this project
  upstreamAgent {
    canBeResolved = true
    canBeConsumed = false
  }
}

dependencies {
  bootstrapLibs(project(":bootstrap"))

  javaagentLibs(project(":custom"))
  javaagentLibs(project(":instrumentation:servlet-3"))

  upstreamAgent("io.opentelemetry.javaagent:opentelemetry-javaagent:${versions.opentelemetryJavaagent}")
}

CopySpec isolateClasses(Iterable<File> jars) {
  return copySpec {
    jars.forEach {
      from(zipTree(it)) {
        into("inst")
        rename("^(.*)\\.class\$", "\$1.classdata")
        // Rename LICENSE file since it clashes with license dir on non-case sensitive FSs (i.e. Mac)
        rename("^LICENSE\$", "LICENSE.renamed")
        exclude("META-INF/INDEX.LIST")
        exclude("META-INF/*.DSA")
        exclude("META-INF/*.SF")
        exclude("META-INF/maven/**")
        exclude("META-INF/MANIFEST.MF")
      }
    }
  }
}

tasks {
  jar {
    enabled = false
  }

  // building the final javaagent jar is done in 3 steps:

  // 1. all distro specific javaagent libs are relocated
  task relocateJavaagentLibs(type: ShadowJar) {
    configurations = [project.configurations.javaagentLibs]

    duplicatesStrategy = DuplicatesStrategy.FAIL

    archiveFileName.set("javaagentLibs-relocated.jar")

    mergeServiceFiles()
    exclude("**/module-info.class")
    relocatePackages(it)

    // exclude known bootstrap dependencies - they can't appear in the inst/ directory
    dependencies {
      exclude("io.opentelemetry:opentelemetry-api")
      exclude("io.opentelemetry:opentelemetry-context")
      // events API and metrics advice API
      exclude("io.opentelemetry:opentelemetry-api-incubator")
    }
  }

  // 2. the distro javaagent libs are then isolated - moved to the inst/ directory
  // having a separate task for isolating javaagent libs is required to avoid duplicates with the upstream javaagent
  // duplicatesStrategy in shadowJar won't be applied when adding files with with(CopySpec) because each CopySpec has
  // its own duplicatesStrategy
  task isolateJavaagentLibs(type: Copy) {
    dependsOn(tasks.relocateJavaagentLibs)
    with isolateClasses(tasks.relocateJavaagentLibs.outputs.files)

    into(layout.buildDirectory.dir("isolated/javaagentLibs"))
  }

  // 3. the relocated and isolated javaagent libs are merged together with the bootstrap libs (which undergo relocation
  // in this task) and the upstream javaagent jar; duplicates are removed
  shadowJar {
    configurations = [project.configurations.bootstrapLibs, project.configurations.upstreamAgent]

    dependsOn(tasks.isolateJavaagentLibs)
    from(tasks.isolateJavaagentLibs.outputs)

    archiveClassifier.set("all")

    duplicatesStrategy = DuplicatesStrategy.EXCLUDE

    mergeServiceFiles {
      include("inst/META-INF/services/*")
    }
    exclude("**/module-info.class")
    relocatePackages(it)

    manifest {
      attributes.put("Main-Class", "io.opentelemetry.javaagent.OpenTelemetryAgent")
      attributes.put("Agent-Class", "io.opentelemetry.javaagent.OpenTelemetryAgent")
      attributes.put("Premain-Class", "io.opentelemetry.javaagent.OpenTelemetryAgent")
      attributes.put("Can-Redefine-Classes", "true")
      attributes.put("Can-Retransform-Classes", "true")
      attributes.put("Implementation-Vendor", "Demo")
      attributes.put("Implementation-Version", "demo-${project.version}-otel-${versions.opentelemetryJavaagent}")
    }
  }

  assemble {
    dependsOn(shadowJar)
  }
}
