import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile

/*
 * Copyright (c) 2018, 2023 Oracle and/or its affiliates.
 *
 * Licensed 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.
 */

plugins {
    id 'java'
    id 'org.kordamp.gradle.jandex' version '2.3.0'
    id 'com.google.protobuf' version '0.10.0'
    id 'org.jetbrains.kotlin.jvm' version '2.4.0'
    id 'org.jetbrains.kotlin.plugin.allopen' version '2.4.0'
    id 'org.jetbrains.kotlin.plugin.jpa' version '2.4.0'
    id 'application'
    id 'pmd'
}

allOpen {
    annotation('jakarta.persistence.Entity')
}

application {
    applicationDefaultJvmArgs = ['--sun-misc-unsafe-memory-access=allow', '--enable-native-access=ALL-UNNAMED']
}

version = '2.0.1'
jandex {
    version = '3.6.0'
}

allOpen {
    annotation('golf.handicap.entities')
}

def debug = ''
def cache = '-D'
def grpcVersion = '1.75.0'

description = """dodex-helidon-mp"""

tasks.withType(JavaCompile).configureEach {
    options.encoding = 'UTF-8'
}

ext {
    helidonVersion = '4.5.0'
    mainClass = 'dmo.fs.server.DodexMain'
}

repositories {
    mavenCentral()
    mavenLocal()
    gradlePluginPortal()
}

java {
    sourceCompatibility = JavaVersion.VERSION_25
    targetCompatibility = JavaVersion.VERSION_25
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(targetCompatibility.toString())
    }
}

println('Java Version: ' + JavaVersion.current() + ' -- target: ' + java.targetCompatibility)

dependencies {
    constraints {
        implementation("org.antlr:antlr4-runtime:4.10.1") {
            because("See protobuf task below: only protoc:4.31.1 and protoc-gen-grpc-java:1.73.0 seem to work")
        }
    }
    implementation enforcedPlatform("io.helidon:helidon-dependencies:${project.helidonVersion}")
    implementation 'io.helidon.microprofile.bundles:helidon-microprofile-core'
    implementation 'io.helidon.common:helidon-common:${project.helidonVersion}'
    implementation 'io.helidon.logging:helidon-logging-common:${project.helidonVersion}'
    implementation 'io.helidon.logging:helidon-logging-log4j:${project.helidonVersion}'

    implementation 'io.helidon.webserver:helidon-webserver:$project.helidonVersion'
    implementation 'jakarta.json.bind:jakarta.json.bind-api'
    implementation 'org.glassfish.jersey.media:jersey-media-json-binding'
    implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.22.0'
    implementation 'io.helidon.microprofile.websocket:helidon-microprofile-websocket:${project.helidonVersion}'

    implementation 'io.helidon.integrations.cdi:helidon-integrations-cdi-hibernate:${project.helidonVersion}'
    implementation 'io.helidon.integrations.cdi:helidon-integrations-cdi-datasource-hikaricp:${project.helidonVersion}'
    implementation 'io.helidon.integrations.cdi:helidon-integrations-cdi-jta-weld:${project.helidonVersion}'
    implementation 'io.helidon.integrations.cdi:helidon-integrations-cdi-jpa:${project.helidonVersion}'
    implementation 'org.hibernate.validator:hibernate-validator:8.0.4.Final'
    implementation 'jakarta.annotation:jakarta.annotation-api'
    implementation 'jakarta.enterprise:jakarta.enterprise.cdi-api'
    implementation 'jakarta.inject:jakarta.inject-api'
    implementation 'jakarta.ws.rs:jakarta.ws.rs-api'
    implementation 'jakarta.persistence:jakarta.persistence-api'
    implementation 'jakarta.transaction:jakarta.transaction-api'
    implementation 'jakarta.xml.bind:jakarta.xml.bind-api'
    implementation 'org.glassfish:jakarta.el'
    runtimeOnly 'jakarta.activation:jakarta.activation-api'

    implementation 'com.h2database:h2:2.4.240'
    implementation 'org.postgresql:postgresql:42.7.12'
    implementation 'org.mariadb.jdbc:mariadb-java-client:3.5.9'
    implementation 'com.oracle.database.jdbc:ojdbc11:23.26.2.0.0'
    implementation 'com.microsoft.sqlserver:mssql-jdbc:13.4.0.jre11'
    implementation 'com.ibm.db2:jcc:12.1.5.0'

    implementation 'io.helidon.common:helidon-common:${project.helidonVersion}'

    implementation 'io.helidon.microprofile:helidon-microprofile-cors:${project.helidonVersion}'

    implementation 'io.helidon.microprofile.openapi:helidon-microprofile-openapi:${project.helidonVersion}'
    runtimeOnly 'io.helidon.integrations.openapi-ui:helidon-integrations-openapi-ui:${project.helidonVersion}'
    runtimeOnly 'org.eclipse.microprofile.openapi:microprofile-openapi-api:4.1.1'
    runtimeOnly 'io.smallrye:smallrye-open-api-ui'

    implementation 'io.helidon.microprofile:helidon-microprofile-security:${project.helidonVersion}'
    implementation 'io.helidon.common:helidon-common-reactive:${project.helidonVersion}'

    implementation 'org.eclipse.microprofile.config:microprofile-config-api:${project.helidonVersion}'

    implementation 'io.grpc:grpc-protobuf:${grpcVersion}'
    implementation 'io.grpc:grpc-services:${grpcVersion}'
    implementation 'io.grpc:grpc-stub:${grpcVersion}'

    implementation 'io.helidon.webserver:helidon-webserver-grpc:${project.helidonVersion}'
    implementation 'io.helidon.webclient:helidon-webclient-grpc:${project.helidonVersion}'
    implementation 'io.helidon.grpc:helidon-grpc-core:${project.helidonVersion}'
    implementation 'io.grpc:grpc-api:${project.helidonVersion}'


    implementation 'io.helidon.webserver.observe:helidon-webserver-observe-health:${project.helidonVersion}'
    implementation 'io.helidon.health:helidon-health-checks:${project.helidonVersion}'
    implementation 'io.helidon.scheduling:helidon-scheduling:${project.helidonVersion}'

    implementation 'io.helidon.microprofile.grpc:helidon-microprofile-grpc-core:${project.helidonVersion}'
    implementation 'io.helidon.microprofile.grpc:helidon-microprofile-grpc-server:${project.helidonVersion}'
    implementation 'io.helidon.microprofile.grpc:helidon-microprofile-grpc-client:${project.helidonVersion}'

    implementation 'io.helidon.grpc:helidon-grpc-api:${project.helidonVersion}'
    implementation 'io.helidon.microprofile.grpc:helidon-microprofile-grpc-tracing:${project.helidonVersion}'
    implementation 'javax.annotation:javax.annotation-api'
    annotationProcessor('org.hibernate.orm:hibernate-jpamodelgen:7.2.21.Final')

    implementation 'org.apache.logging.log4j:log4j-core:2.26.1'
    implementation 'org.apache.logging.log4j:log4j-api:2.26.1'

    implementation 'io.helidon.build-tools.devloop:helidon-build-devloop:4.0.27'
    implementation 'org.jinq:jinq:2.0.3'

    testImplementation 'org.hamcrest:hamcrest:2.2'
    testImplementation 'io.helidon.microprofile.testing:helidon-microprofile-testing-junit5'
    testImplementation 'io.helidon.microprofile.tests:helidon-microprofile-tests-junit5:4.0.0-M2'
    testImplementation 'org.junit.jupiter:junit-jupiter-api'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.13.4'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    testImplementation 'io.helidon.webserver.testing.junit5:helidon-webserver-testing-junit5:$project.helidonVersion'
    testImplementation 'io.helidon.common.testing:helidon-common-testing-junit5:$project.helidonVersion'
    testImplementation 'io.helidon.microprofile.testing:helidon-microprofile-testing-junit5:$project.helidonVersion'
    testImplementation 'io.helidon.common.testing:helidon-common-testing-http-junit5:$project.helidonVersion'
    implementation 'io.helidon.webclient:helidon-webclient-websocket:$project.helidonVersion'
    testImplementation 'io.helidon.webserver.testing.junit5:helidon-webserver-testing-junit5-grpc:$project.helidonVersion'
}

configurations.configureEach {
    resolutionStrategy {
        force "org.antlr:antlr4-runtime:4.10.1"
    }
}

def mode

run {
    if (System.getProperty('DEBUG', 'false') == 'true') {
        debug = '--java-opts=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Dvertx.disableFileCaching=true'
        cache = ''
    }

    mode = environment.get('MODE')

    if (mode == null && project.gradle.startParameter.taskNames.contains('run')) {
        mode = 'dev'
        environment 'MODE', mode
    }
    args = ['run', mainClass, cache, debug]
}

test {
    useJUnitPlatform()
    // Use junit platform for unit tests
    testLogging {
        events 'PASSED', 'FAILED', 'SKIPPED'
    }
}

// define a custom task to copy all dependencies in the runtime classpath
// into build/libs/libs
// uses built-in Copy
tasks.register('copyLibs', Copy) {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    from configurations.runtimeClasspath
    into 'build/libs/libs'
}

// add it as a dependency of built-in task 'assemble'
copyLibs.dependsOn jar
assemble.dependsOn copyLibs

// default jar configuration
// set the main classpath
// add each jar under build/libs/libs into the classpath
distTar {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
distZip {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
compileJava {
    options.deprecation = true
}

jar {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    archiveFileName = project.name + '.jar'
    manifest {
        attributes('Main-Class': mainClass,
                'Class-Path': configurations.runtimeClasspath.files.collect { "libs/$it.name" }.join(' ')
        )
    }
    dependsOn 'jandex'
}

application {
    mainClass = project.mainClass
}

// This is a work-around for running unit tests.
// Gradle places resource files under ${buildDir}/resources. In order for
// beans.xml to get picked up by CDI it must be co-located with the classes.
// So we move it before running tests.
// In either case it ends up AOK in the final jar artifact
tasks.register('moveBeansXML') {

    doLast {
        if (mode == "dev") {
            ant.copy file: getLayout().getProjectDirectory().toString() + '/src/main/resources/META-INF/beans.xml',
                    todir: getLayout().getBuildDirectory().get().toString() + '/classes/java/main/META-INF'
        } else {
            ant.move file: getLayout().getBuildDirectory().get().toString() + '/resources/main/META-INF/beans.xml',
                    todir: getLayout().getBuildDirectory().get().toString() + '/classes/java/main/META-INF'
        }
    }
}
pmd {
    ruleSetFiles = files('dodexstart.xml')
    ruleSets = []
    ignoreFailures = true
    // gradle not ready for PMD 7 with jdk21 (ClassNotFoundException: net.sourceforge.pmd.ant.PMDTask)
    toolVersion = '6.55.0'// 7.0.0-rc4
    consoleOutput = false
}

pmdMain {
    dependsOn 'jandex'
}
pmdTest {
    dependsOn 'jandex'
}

compileTestJava.dependsOn 'jandex'
test.dependsOn moveBeansXML
run.dependsOn 'jandex', moveBeansXML

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:4.31.1'
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.73.0'
        }
    }

    generateProtoTasks {
        all().each { task ->
            task.plugins { grpc{} }
        }
        ofSourceSet('main')
    }
}
