/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java library project to get you started.
 * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
 * User Manual available at https://docs.gradle.org/7.3.3/userguide/building_java_projects.html
 */

plugins {
    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
    id 'signing'
    id 'maven-publish'
    id 'org.jreleaser' version '1.20.0'
    id 'jacoco'
    id 'jvm-test-suite'
    id 'jacoco-report-aggregation'
    id 'checkstyle'
    id 'com.github.johnrengelman.shadow' version '7.1.2'
    id 'org.revapi.revapi-gradle-plugin' version '1.8.0'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

group = 'software.amazon.nio.s3'
archivesBaseName = 'nio-spi-for-s3'
version = '2.2.1'

java {
    withSourcesJar()
    withJavadocJar()
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}

// Process version.properties to replace placeholders with actual values
processResources {
    filesMatching('version.properties') {
        expand(project: project)
    }
}

tasks.withType(JavaCompile).configureEach {
    options.release.set(11)
    options.compilerArgs += ['-Xlint:all,-serial']
}

sourceSets {
    examples {
        java {
        }
    }
}

dependencies {
    implementation 'io.reactivex.rxjava3:rxjava:3.1.12'

    implementation platform('software.amazon.awssdk:bom:2.34.0')

    implementation('software.amazon.awssdk:s3') {
        exclude group: 'software.amazon.awssdk', module: 'apache-client'
    }
    implementation('software.amazon.awssdk:s3-transfer-manager') {
        exclude group: 'software.amazon.awssdk', module: 'apache-client'
    }
    implementation 'software.amazon.awssdk.crt:aws-crt:0.39.0'
    implementation 'org.slf4j:slf4j-api:2.0.17'
    implementation 'com.github.ben-manes.caffeine:caffeine:3.1.8'

    examplesImplementation project
    examplesImplementation 'org.slf4j:slf4j-api:2.0.17'
}

publishing {
    publications {
        maven(MavenPublication) {
            from components.java
            pom {
                name = 'AWS Java NIO SPI for S3'
                description = 'A Java NIO.2 service provider for S3, allowing Java NIO operations to be performed on paths using the `s3` scheme. This\n' +
                        'package implements the service provider interface (SPI) defined for Java NIO.2 in JDK 1.7 providing "plug-in" non-blocking\n' +
                        'access to S3 objects for Java applications using Java NIO.2 for file access.'
                url = 'https://github.com/awslabs/aws-java-nio-spi-for-s3'
                inceptionYear = '2022'
                scm {
                    url = 'https://github.com/awslabs/aws-java-nio-spi-for-s3/tree/main'
                    connection = 'scm:git:ssh://git@github.com/awslabs/aws-java-nio-spi-for-s3.git'
                    developerConnection = 'scm:git:ssh://git@github.com/awslabs/aws-java-nio-spi-for-s3.git'
                }

                licenses {
                    license {
                        name = 'The Apache License, Version 2.0'
                        url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
                        distribution = 'repo'
                    }
                }

                developers {
                    developer {
                        id = 'markjschreiber'
                        name = 'Mark Schreiber'
                        email = 'mrschre@amazon.com'
                    }
                }
            }
        }
    }
    repositories {
        maven {
            url = layout.buildDirectory.dir('staging-deploy')
        }
    }
}

signing {
    def signingKey = findProperty('jreleaser.gpg.secret.key')?.toString()?.replace('\\', '')
    def signingPassword = findProperty('jreleaser.gpg.passphrase')

    if (signingKey && signingPassword) {
        useInMemoryPgpKeys(signingKey, signingPassword)
    } else {
        useGpgCmd()
        // The key ID will be selected by the gpg command
    }

    sign publishing.publications.maven
}

jreleaser {
    signing {
        active = 'ALWAYS'  // Keep signing active
        armored = true
        mode = 'COMMAND'  // Use the GPG command instead of in-memory keys
        // The key ID is set in ~/.gnupg/gpg.conf
    }
    deploy {
        maven {
            mavenCentral {
                sonatype {
                    active = 'ALWAYS'
                    url = 'https://central.sonatype.com/api/v1/publisher'
                    stagingRepository('build/staging-deploy')
                    sign = false  // Disable signing during deployment since files are already signed
                }
            }
        }
    }
}


javadoc {
    if (JavaVersion.current().isJava9Compatible()) {
        options.addBooleanOption('html5', true)
    }
}

// JVM test suite plugin https://docs.gradle.org/7.3.3/userguide/jvm_test_suite_plugin.html
testing {
    suites {
        integrationTest(JvmTestSuite) {
            dependencies {
                implementation(project())
                implementation('org.testcontainers:junit-jupiter:1.21.3')
                implementation('org.testcontainers:localstack:1.21.3')
                implementation('org.testcontainers:testcontainers:1.21.3')
            }
        }
        withType(JvmTestSuite).configureEach {
            useJUnitJupiter('5.11.4')
            targets {
                all {
                    testTask.configure {
                        systemProperty "aws.region",  "us-east-1"
                    }
                }
            }
            dependencies {
                implementation('org.assertj:assertj-core:3.27.6')
                implementation('org.mockito:mockito-core:5.20.0')
                implementation('org.mockito:mockito-junit-jupiter:5.20.0')
                implementation('com.github.stefanbirkner:system-lambda:1.2.1')
                runtimeOnly('ch.qos.logback:logback-classic:1.5.18')
            }
        }
    }
}

reporting {
    reports {
        testFullCodeCoverageReport(JacocoCoverageReport) {
            testType = 'full'
        }
    }
}

tasks.named('testFullCodeCoverageReport') {
    dependsOn( testCodeCoverageReport, integrationTestCodeCoverageReport )
    executionData fileTree( project.buildDir.absolutePath ).include( "jacoco/*.exec" )
}

jacocoTestReport {
    dependsOn test
    reports {
        xml.required = true
        xml.outputLocation = file("build/reports/coverage.xml")
    }
}

checkstyle {
    toolVersion = '10.12.5'
    configDirectory.set(new File(projectDir, ".checkstyle"))
}

jacocoTestCoverageVerification {
    violationRules {
        // Default rule for most classes - 80% threshold
        rule {
            element = 'CLASS'
            excludes = [
                // Exclude classes that have specific rules below
                'software.amazon.nio.spi.s3.S3ReadAheadByteChannel',
                'software.amazon.nio.spi.s3.S3SeekableByteChannel', 
                'software.amazon.nio.spi.s3.S3FileSystem',
                'software.amazon.nio.spi.s3.S3DirectoryStream',
                'software.amazon.nio.spi.s3.S3WritableByteChannel',
                'software.amazon.nio.spi.s3.S3FileSystemProvider',
                'software.amazon.nio.spi.s3.util.LibraryVersion',
                'software.amazon.nio.spi.s3.S3ClientProvider.S3NioSpiInterceptor'
            ]
            limit {
                counter = 'LINE'
                value = 'COVEREDRATIO'
                minimum = 0.80
            }
            limit {
                counter = 'BRANCH'
                value = 'COVEREDRATIO'
                minimum = 0.80
            }
        }
        
        // Utility classes - lower threshold (73% line, 50% branch)
        rule {
            element = 'CLASS'
            includes = ['software.amazon.nio.spi.s3.util.LibraryVersion']
            limit {
                counter = 'LINE'
                value = 'COVEREDRATIO'
                minimum = 0.73  // Current actual coverage
            }
            limit {
                counter = 'BRANCH'
                value = 'COVEREDRATIO'
                minimum = 0.44
            }
        }
        
        // Infrastructure classes with complex I/O - 75% line, 60% branch
        rule {
            element = 'CLASS'
            includes = [
                'software.amazon.nio.spi.s3.S3ReadAheadByteChannel',
                'software.amazon.nio.spi.s3.S3SeekableByteChannel',
                'software.amazon.nio.spi.s3.S3WritableByteChannel'
            ]
            limit {
                counter = 'LINE'
                value = 'COVEREDRATIO'
                minimum = 0.75
            }
            limit {
                counter = 'BRANCH'
                value = 'COVEREDRATIO'
                minimum = 0.60
            }
        }
        
        // Core system classes - 74% line, 65% branch
        rule {
            element = 'CLASS'
            includes = [
                'software.amazon.nio.spi.s3.S3FileSystem',
                'software.amazon.nio.spi.s3.S3DirectoryStream'
            ]
            limit {
                counter = 'LINE'
                value = 'COVEREDRATIO'
                minimum = 0.74  // Adjusted for S3DirectoryStream
            }
            limit {
                counter = 'BRANCH'
                value = 'COVEREDRATIO'
                minimum = 0.65
            }
        }
        
        // Main provider class - 70% line, 60% branch (most complex)
        rule {
            element = 'CLASS'
            includes = ['software.amazon.nio.spi.s3.S3FileSystemProvider']
            limit {
                counter = 'LINE'
                value = 'COVEREDRATIO'
                minimum = 0.70
            }
            limit {
                counter = 'BRANCH'
                value = 'COVEREDRATIO'
                minimum = 0.60
            }
        }
        
        // Simple interceptor class - very low threshold
        rule {
            element = 'CLASS'
            includes = ['software.amazon.nio.spi.s3.S3ClientProvider.S3NioSpiInterceptor']
            limit {
                counter = 'LINE'
                value = 'COVEREDRATIO'
                minimum = 0.20  // Current actual coverage
            }
        }
    }
}

// Make the check task depend on coverage verification
check.dependsOn jacocoTestCoverageVerification

// Ensure test coverage verification runs after tests
jacocoTestCoverageVerification.dependsOn jacocoTestReport
