import org.elasticsearch.hadoop.gradle.scala.SparkVariantPlugin

description = "Elasticsearch Spark Core"

apply plugin: 'java-library'
apply plugin: 'scala'
apply plugin: 'es.hadoop.build'
apply plugin: 'spark.variants'

sparkVariants {
    capabilityGroup 'org.elasticsearch.spark.variant'

    // Changing the formatting of these lines could break .buildkite/pipeline.py, it uses regex to parse the `spark30scala212` part
    // We should maybe move these to a separate config file that can be read from both this file and the pipeline script in the future if it creates issues
    setCoreDefaultVariant "spark30scala213", spark30Version, scala213Version
    addCoreFeatureVariant "spark30scala212", spark30Version, scala212Version

    all { SparkVariantPlugin.SparkVariant variant ->

        String scalaCompileTaskName = project.sourceSets
                .getByName(variant.getSourceSetName("main"))
                .getCompileTaskName("scala")

        // Configure main compile task
        project.getTasks().getByName(scalaCompileTaskName) { ScalaCompile compileScala ->
            configure(compileScala.scalaCompileOptions.forkOptions) {
                memoryMaximumSize = '1g'
            }
            compileScala.scalaCompileOptions.additionalParameters = [
                    "-feature",
                    "-unchecked",
                    "-deprecation",
                    "-Xfuture",
                    "-Yno-adapted-args",
                    "-Ywarn-dead-code",
                    "-Ywarn-numeric-widen",
                    "-Xfatal-warnings"
            ]
        }

        dependencies {
            add(variant.configuration('api'), "org.scala-lang:scala-library:${variant.scalaVersion}")
            add(variant.configuration('api'), "org.scala-lang:scala-reflect:${variant.scalaVersion}")
            add(variant.configuration('api'), "org.apache.spark:spark-core_${variant.scalaMajorVersion}:${variant.sparkVersion}") {
                exclude group: 'org.apache.hadoop'
            }

            add(variant.configuration('implementation'), project(":elasticsearch-hadoop-mr"))
            add(variant.configuration('implementation'), "commons-logging:commons-logging:1.1.1")

            add(variant.configuration('compileOnly'), "com.fasterxml.jackson.module:jackson-module-scala_${variant.scalaMajorVersion}:2.9.10")
            add(variant.configuration('compileOnly'), "com.fasterxml.jackson.core:jackson-annotations:2.6.7")
            add(variant.configuration('compileOnly'), "com.google.guava:guava:14.0.1")
            add(variant.configuration('compileOnly'), "org.slf4j:slf4j-api:${project.ext.slf4jVersion}")

            add(variant.configuration('test', 'implementation'), project(":test:shared"))
            add(variant.configuration('test', 'implementation'), "com.esotericsoftware:kryo:4.0.2")
            add(variant.configuration('test', 'implementation'), "org.apache.spark:spark-core_${variant.scalaMajorVersion}:${variant.sparkVersion}") {
                exclude group: 'org.apache.hadoop'
            }

            add(variant.configuration('itest', 'implementation'), project(":test:shared"))
            add(variant.configuration('test', 'implementation'), "org.elasticsearch:securemock:1.2")
            add(variant.configuration('additionalSources'), project(":elasticsearch-hadoop-mr"))
            add(variant.configuration('javadocSources'), project(":elasticsearch-hadoop-mr"))
        }

        def javaFilesOnly = { FileTreeElement spec ->
            spec.file.name.endsWith('.java') || spec.isDirectory()
        }

        // Add java files from scala source set to javadocSourceElements.
        project.fileTree("src/main/scala").include(javaFilesOnly).each {
            project.artifacts.add(variant.configuration('javadocSourceElements'), it)
        }

        // Configure java source generation for javadoc purposes
        if (variant.scalaMajorVersion != '2.10') {
            String generatedJavaDirectory = "$buildDir/generated/java/${variant.name}"
            Configuration scalaCompilerPlugin = project.configurations.maybeCreate(variant.configuration('scalaCompilerPlugin'))
            scalaCompilerPlugin.defaultDependencies { dependencies ->
                dependencies.add(project.dependencies.create("com.typesafe.genjavadoc:genjavadoc-plugin_${variant.scalaVersion}:0.18"))
            }

            ScalaCompile compileScala = tasks.getByName(scalaCompileTaskName) as ScalaCompile
            compileScala.scalaCompileOptions.with {
                additionalParameters = [
                        "-Xplugin:" + configurations.getByName(variant.configuration('scalaCompilerPlugin')).asPath,
                        "-P:genjavadoc:out=$generatedJavaDirectory".toString()
                ]
            }
            // Export generated Java code from the genjavadoc compiler plugin
            artifacts {
                add(variant.configuration('javadocSourceElements'), project.file(generatedJavaDirectory)) {
                    builtBy compileScala
                }
            }
            tasks.getByName(variant.taskName('javadoc')) {
                dependsOn compileScala
                source(generatedJavaDirectory)
            }
        }

        scaladoc {
            title = "${rootProject.description} ${version} API"
        }
    }
}

if (JavaVersion.current() >= JavaVersion.VERSION_17) {
    tasks.withType(Test) { Test task ->
        if (task.getName().startsWith("test")) 
            task.configure {
                jvmArgs "--add-opens=java.base/java.io=ALL-UNNAMED" // Needed for IOUtils's BYTE_ARRAY_BUFFER reflection
                jvmArgs "--add-opens=java.base/java.nio=ALL-UNNAMED" // Needed for org.apache.spark.SparkConf, which indirectly uses java.nio.DirectByteBuffer
                jvmArgs "--add-opens=java.base/java.lang=ALL-UNNAMED" // Needed for secure mock
            }
    }
}

// Set minimum compatibility and java home for compiler task
tasks.withType(ScalaCompile) { ScalaCompile task ->
    task.scalaCompileOptions.additionalParameters = ["-javabootclasspath", new File(project.ext.runtimeJavaHome, 'jre/lib/rt.jar').absolutePath]
    task.options.bootstrapClasspath = layout.files(new File(project.ext.runtimeJavaHome, 'jre/lib/rt.jar'))
    task.sourceCompatibility = project.ext.minimumRuntimeVersion
    task.targetCompatibility = project.ext.minimumRuntimeVersion
    task.options.forkOptions.executable = new File(project.ext.runtimeJavaHome, 'bin/java').absolutePath
}
