package io.opentelemetry.gradle

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.kotlin.dsl.the
import java.io.File

/**
 * This gradle plugin will define a new task called generateOtelVersionClass.
 * This task generates a Java source file that contains the project version
 * as a string constant. The "compileJava" task is updated to depend on
 * generateOtelVersionClass, and the project source set is updated to
 * include the new file.
 */
class OtelVersionClassPlugin : Plugin<Project> {
  override fun apply(project: Project) {
    project.plugins.apply(JavaPlugin::class.java)

    project.task("generateOtelVersionClass") {
      doLast {
        writeFile(project)
      }
    }
    // Add dependency on this task
    project.tasks.getByName("compileJava") {
      dependsOn("generateOtelVersionClass")
    }
    // Add new source dir to the "main" source set
    val outDir = buildOutDir(project)
    val java = project.the<JavaPluginExtension>()
    java.sourceSets.getByName("main").java {
      srcDir(outDir)
    }
  }

  private fun writeFile(project: Project) {
    val group = "${project.group}".replace('.', '/')
    val projectName = project.name.replace('-', '/')
    val outDir = buildOutDir(project)
    val filename = "$group/$projectName/internal/OtelVersion.java"
    val outFile = File(outDir, filename)
    val packageName = "${project.group}.${project.name.replace('-', '.')}.internal"
    val classBody = getClassBody("${project.version}", packageName)

    outFile.parentFile.mkdirs()
    outFile.writeText(classBody)
  }

  private fun getClassBody(version: String, packageName: String): String {
    return """
      package $packageName;
      
      import javax.annotation.Generated;
      
      /** Autogenerated class do not edit. */
      @Generated("io.opentelemetry.gradle.OtelVersionClassPlugin")
      public final class OtelVersion {
        public static final String VERSION = "$version";

        private OtelVersion() {}
      }
    """.trimIndent()
  }

  private fun buildOutDir(project: Project): File {
    return File(project.layout.buildDirectory.asFile.get(), "generated/sources/version/java/main")
  }
}
