/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.nio.file.Paths

buildscript {
    dependencies {
        classpath("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml") {
            version { strictly("2.14.3") }
        }
    }
}

plugins {
    id('idea')
    // a java project
    id('java')
    // which produces test fixtures
    id('java-test-fixtures')
    // and is published
    id('maven-publish')
    // and produces a docker image
    id('com.google.cloud.tools.jib') version '3.4.4'
    // and generates an openAPI specification
    id('io.smallrye.openapi') version "${smallryeOpenApiVersion}"
}
apply from: "$rootDir/gradle/common/publishing.gradle"

// Configure SmallRye OpenAPI plugin
generateOpenApiSpec {
    outputDirectory = layout.buildDirectory.dir('resources/main/openapi')
}

sourceCompatibility = JavaVersion.VERSION_11

// add additional test source set
sourceSets {
    integrationTest {
        java {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('src/test/integration')
        }
    }

    containerTest {
        java {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('src/test/containerTest')
        }
    }
}

// and mark it as test root
idea {
    module {
        testSourceDirs += sourceSets.integrationTest.java.srcDirs
        testSourceDirs += sourceSets.containerTest.java.srcDirs
    }
}

configurations {
    integrationTestImplementation.extendsFrom testImplementation
    containerTestImplementation.extendsFrom testImplementation
}

dependencies {
    compileOnly('org.jetbrains:annotations:23.0.0')
    testCompileOnly('org.jetbrains:annotations:23.0.0')
    integrationTestCompileOnly('org.jetbrains:annotations:23.0.0')

    implementation("io.vertx:vertx-web:${project.vertxVersion}") {
        exclude group: 'junit', module: 'junit'
    }
    implementation("io.vertx:vertx-dropwizard-metrics:${project.vertxVersion}")
    implementation("io.vertx:vertx-web-client:${project.vertxVersion}")
    implementation("io.vertx:vertx-auth-jwt:$vertxVersion")
    implementation("io.vertx:vertx-auth-oauth2:$vertxVersion")

    implementation('com.datastax.cassandra:cassandra-driver-core:3.11.3')
    implementation("com.google.inject:guice:${guiceVersion}")
    implementation("com.github.ben-manes.caffeine:caffeine:2.9.3")

    implementation("org.slf4j:slf4j-api:${project.slf4jVersion}")
    implementation("ch.qos.logback:logback-core:${project.logbackVersion}")
    implementation("ch.qos.logback:logback-classic:${project.logbackVersion}")


    implementation(group: 'org.apache.commons', name: 'commons-lang3', version: '3.13.0')
    implementation(group: 'commons-codec', name: 'commons-codec', version: "${project.commonsCodecVersion}")

    // Jackson for yaml-based configuration parsing
    implementation(group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${project.jacksonVersion}")
    implementation(group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: "${project.jacksonVersion}")

    // aws sdk BOM + s3
    implementation platform(group: 'software.amazon.awssdk', name:'bom', version:"${project.awsSdkVersion}")
    implementation('software.amazon.awssdk:s3')
    implementation('software.amazon.awssdk:netty-nio-client')
    implementation('io.netty:netty-transport-classes-epoll') {
        version {
            // Some integration tests are failing with version 4.1.100.final due to netty bootstrapping issue in cassandra java driver.
            // Force the version to the old version unblocks the integration test.
            strictly '4.1.86.Final'
        }
    }

    implementation(group: 'io.netty', name: 'netty-tcnative-boringssl-static', version: "${project.boringSslVersion}")  // for openSSL

    // The newer versions (2.0.48.Final+) of tcnative require explicit dependency declarations,
    // including the classifiers. See https://netty.io/wiki/forked-tomcat-native.html#gradle-and-bazel
    // for details.

    // openSSL native libraries for linux x86-64 architectures
    implementation(group: 'io.netty', name: 'netty-tcnative-boringssl-static', version: "${project.boringSslVersion}", classifier: 'linux-x86_64')
    // openSSL native libraries for macOS aarch-64 architectures
    implementation(group: 'io.netty', name: 'netty-tcnative-boringssl-static', version: "${project.boringSslVersion}", classifier: 'osx-aarch_64')
    // openSSL native libraries for linux aarch-64 architectures
    implementation(group: 'io.netty', name: 'netty-tcnative-boringssl-static', version: "${project.boringSslVersion}", classifier: 'linux-aarch_64')
    // openSSL native libraries for macOS x86-64 architectures
    implementation(group: 'io.netty', name: 'netty-tcnative-boringssl-static', version: "${project.boringSslVersion}", classifier: 'osx-x86_64')

    // DataHub client is used to convert and report Cassandra schema on a periodic basis
    implementation(group: 'io.acryl', name: 'datahub-client', version: '0.15.0-3')
    
    // OpenAPI support
    implementation("org.eclipse.microprofile.openapi:microprofile-openapi-api:${project.microprofileOpenApiVersion}")
    implementation("jakarta.ws.rs:jakarta.ws.rs-api:${project.jakartaWsRsVersion}")

    implementation(group: "org.apache.cassandra", name: "cassandra-analytics-common", version: "${[project.analyticsVersion]}")
    implementation(group: "org.apache.cassandra", name: "cassandra-analytics-cdc_spark3_2.12", version: "${[project.analyticsVersion]}")
    implementation "com.esotericsoftware:kryo-shaded:${kryoVersion}"

    testImplementation "org.junit.jupiter:junit-jupiter-api:${project.junitVersion}"
    testImplementation "org.junit.jupiter:junit-jupiter-params:${project.junitVersion}"
    testImplementation "org.assertj:assertj-core:3.24.2"
    testImplementation "org.quicktheories:quicktheories:0.26"
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${project.junitVersion}"

    testImplementation('com.google.guava:guava-testlib:32.0.0-jre') {
        exclude group: 'junit', module: 'junit'
    }

    testImplementation('com.datastax.cassandra:cassandra-driver-core:3.11.3:tests')
    testImplementation('org.mockito:mockito-core:4.10.0')
    testImplementation('org.mockito:mockito-inline:4.10.0')
    testImplementation("io.vertx:vertx-junit5:${project.vertxVersion}")
    testImplementation("com.auth0:java-jwt:4.4.0")
    testImplementation(testFixtures(project(":client-common")))
    testImplementation(testFixtures(project(":server-common")))
    testImplementation(testFixtures(project(":test-common")))

    implementation(project(":server-common"))
    implementation(project(":adapters:adapters-base"))
    implementation(project(":adapters:adapters-cassandra41"))
    implementation(project(":vertx-auth-mtls"))
    implementation(project(":vertx-client"))

    testFixturesApi(testFixtures(project(":server-common")))
    testFixturesApi(testFixtures(project(":vertx-auth-mtls")))
    testFixturesImplementation("io.vertx:vertx-junit5:${project.vertxVersion}")
    testFixturesImplementation("com.google.inject:guice:${guiceVersion}")
    testFixturesImplementation('org.mockito:mockito-core:4.10.0')
    testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:${project.junitVersion}")
    testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:${project.junitVersion}")
    testFixturesImplementation("org.assertj:assertj-core:3.24.2")
    testFixturesImplementation("io.vertx:vertx-web:${project.vertxVersion}") {
        exclude group: 'junit', module: 'junit'
    }
    integrationTestImplementation(testFixtures(project(":test-common")))
    integrationTestImplementation "org.junit.jupiter:junit-jupiter-api:${project.junitVersion}"
    // Needed by the Cassandra dtest framework
    integrationTestImplementation("org.junit.vintage:junit-vintage-engine:${junitVersion}")
    // Needed for snapshot manifest validation
    integrationTestImplementation(group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: "${project.jacksonVersion}")

    containerTestImplementation('com.adobe.testing:s3mock-testcontainers:2.17.0') // 3.x version do not support java 11
}

test {
    systemProperty "vertxweb.environment", "dev"
    systemProperty "vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.SLF4JLogDelegateFactory"
    // There is no native lib (JNR) for getting time for testing
    systemProperty "com.datastax.driver.USE_NATIVE_CLOCK", "false"
    // ordinarily we don't need integration tests
    // see the integrationTest task
    useJUnitPlatform()
    reports {
        junitXml.setRequired(true)
        def destDir = Paths.get(rootProject.rootDir.absolutePath, "build", "test-results", "test").toFile()
        println("Destination directory for unit tests: ${destDir}")
        junitXml.getOutputLocation().set(destDir)
        html.setRequired(true)
        html.getOutputLocation().set(destDir)
    }
    testLogging {
        events "passed", "skipped", "failed"
    }
    finalizedBy jacocoTestReport // report is always generated after tests run
}

apply from: "${project.rootDir}/gradle/common/integrationTestTask.gradle"
apply from: "${project.rootDir}/gradle/common/java11Options.gradle"

tasks.register("containerTest", Test) {
    if (JavaVersion.current().isJava11Compatible()) {
        jvmArgs(project.ext.JDK11_OPTIONS)
        println("JVM arguments for $project.name are $allJvmArgs")
    }

    useJUnitPlatform()
    reports {
        junitXml.setRequired(true)
        def destDir = Paths.get(rootProject.rootDir.absolutePath, "build", "test-results", "containerTest").toFile()
        println("Destination directory for testcontainer tests: ${destDir}")
        junitXml.getOutputLocation().set(destDir)
        html.setRequired(true)
        html.getOutputLocation().set(destDir)
    }
    testLogging {
        events "passed", "skipped", "failed"
    }
    testClassesDirs = sourceSets.containerTest.output.classesDirs
    classpath = sourceSets.containerTest.runtimeClasspath
    shouldRunAfter test
    finalizedBy jacocoTestReport // report is always generated after tests run
}

jib {
    from {
        image = 'gcr.io/distroless/java11-debian11@sha256:56ffee16297ae1d3484bd47575cacd8102e5ba2be425a7772b3f8ad0d48def3b'
    }
    to {
        image = "cassandra-sidecar:${project.version}"
    }
}

spotbugsTest.enabled = false
compileContainerTestJava.onlyIf { "true" != System.getenv("skipContainerTest") }
checkstyleContainerTest.onlyIf { "true" != System.getenv("skipContainerTest") }
spotbugsContainerTest.onlyIf { "true" != System.getenv("skipContainerTest") }

check.dependsOn containerTest, integrationTest, jacocoTestReport

// Ensure the OpenAPI spec is generated before building the JAR
processResources.dependsOn generateOpenApiSpec

