// SPDX-FileCopyrightText: 2021 Paul Schaub <info@pgpainless.org>
//
// SPDX-License-Identifier: Apache-2.0

buildscript {

    repositories {

        maven {
            url "https://plugins.gradle.org/m2/"
        }
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath "gradle.plugin.org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.12.0"
    }
}

plugins {
    id 'org.jetbrains.kotlin.jvm' version "1.8.10"
    id 'com.diffplug.spotless' version '6.22.0' apply false
}

apply from: 'version.gradle'

allprojects {
    apply plugin: 'java'
    apply plugin: 'idea'
    apply plugin: 'eclipse'
    apply plugin: 'jacoco'
    apply plugin: 'checkstyle'
    apply plugin: 'kotlin'
    apply plugin: 'com.diffplug.spotless'

    java {
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    compileJava {
        options.release = 8
    }

    // Only generate jar for submodules
    // without this we would generate an empty pgpainless.jar for the project root
    // https://stackoverflow.com/a/25445035
    jar {
        reproducibleFileOrder = true
        onlyIf { !sourceSets.main.allSource.files.isEmpty() }
    }

    // checkstyle
    checkstyle {
        toolVersion = '10.12.1'
    }

    spotless {
      kotlin {
        ktfmt().dropboxStyle()
      }
    }

    group 'org.pgpainless'
    description = "Simple to use OpenPGP API for Java based on Bouncycastle"
    version = shortVersion

    sourceCompatibility = javaSourceCompatibility

    repositories {
        mavenCentral()
        mavenLocal()
    }

    // Reproducible Builds
    tasks.withType(AbstractArchiveTask) {
        preserveFileTimestamps = false
        reproducibleFileOrder = true

        dirMode = 0755
        fileMode = 0644
    }

    // Compatibility of default implementations in kotlin interfaces with Java implementations.
    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
        kotlinOptions {
            freeCompilerArgs += ["-Xjvm-default=all-compatibility"]
        }
    }

    project.ext {
        rootConfigDir = new File(rootDir, 'config')
        gitCommit = getGitCommit()
        isContinuousIntegrationEnvironment = Boolean.parseBoolean(System.getenv('CI'))
        isReleaseVersion = !isSnapshot
        signingRequired = !(isSnapshot || isContinuousIntegrationEnvironment)
        sonatypeCredentialsAvailable = project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')
        sonatypeSnapshotUrl = 'https://oss.sonatype.org/content/repositories/snapshots'
        sonatypeStagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2'
    }

    if (isSnapshot) {
        version = version + '-SNAPSHOT'
    }
    def projectDirFile = new File("$projectDir")
    if (!project.ext.isSnapshot && !'git describe --exact-match HEAD'.execute(null, projectDirFile).text.trim().equals(ext.shortVersion)) {
        throw new InvalidUserDataException('Untagged version detected! Please tag every release.')
    }
    if (!version.endsWith('-SNAPSHOT') && version != 'git tag --points-at HEAD'.execute(null, projectDirFile).text.trim()) {
        throw new InvalidUserDataException(
                'Tag mismatch detected, version is ' + version + ' but should be ' +
                        'git tag --points-at HEAD'.execute(null, projectDirFile).text.trim())
    }

    jacoco {
        toolVersion = "0.8.8"
    }

    jacocoTestReport {
        dependsOn test
        sourceDirectories.setFrom(project.files(sourceSets.main.allSource.srcDirs))
        classDirectories.setFrom(project.files(sourceSets.main.output))
        reports {
            xml.enabled true
        }
    }

    test {
        useJUnitPlatform()
        testLogging {
            events "passed", "skipped", "failed"
            exceptionFormat "full"
        }
    }
}

subprojects {
    apply plugin: 'maven-publish'
    apply plugin: 'signing'

    task sourcesJar(type: Jar, dependsOn: classes) {
        classifier = 'sources'
        from sourceSets.main.allSource
    }
    task javadocJar(type: Jar, dependsOn: javadoc) {
        classifier = 'javadoc'
        from javadoc.destinationDir
    }
    task testsJar(type: Jar, dependsOn: testClasses) {
        classifier = 'tests'
        from sourceSets.test.output
    }

    publishing {
        publications {
            mavenJava(MavenPublication) {
                from components.java
                artifact sourcesJar
                artifact javadocJar
                artifact testsJar
                pom {
                    name = 'PGPainless'
                    description = 'Simple to use OpenPGP API for Java based on Bouncycastle'
                    url = 'https://github.com/pgpainless/pgpainless'
                    inceptionYear = '2018'

                    scm {
                        url = 'https://github.com/pgpainless/pgpainless'
                        connection = 'scm:https://github.com/pgpainless/pgpainless'
                        developerConnection = 'scm:git://github.com/pgpainless/pgpainless.git'
                    }

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

                    developers {
                        developer {
                            id = 'vanitasvitae'
                            name = 'Paul Schaub'
                            email = 'vanitasvitae@fsfe.org'
                        }
                    }
                }
            }
        }
        repositories {
            if (sonatypeCredentialsAvailable) {
                maven {
                    url isSnapshot ? sonatypeSnapshotUrl : sonatypeStagingUrl
                    credentials {
                        username = sonatypeUsername
                        password = sonatypePassword
                    }
                }
            }
        }
    }

    signing {
        useGpgCmd()
        required { signingRequired }
        sign publishing.publications.mavenJava
    }
}

def getGitCommit() {
    def projectDirFile = new File("$projectDir")
    def dotGit = new File("$projectDir/.git")
    if (!dotGit.isDirectory()) return 'non-git build'

    def cmd = 'git describe --always --tags --dirty=+'
    def proc = cmd.execute(null, projectDirFile)
    def gitCommit = proc.text.trim()
    assert !gitCommit.isEmpty()

    def srCmd = 'git symbolic-ref --short HEAD'
    def srProc = srCmd.execute(null, projectDirFile)
    srProc.waitForOrKill(10 * 1000)
    if (srProc.exitValue() == 0) {
        // Only add the information if the git command was
        // successful. There may be no symbolic reference for HEAD if
        // e.g. in detached mode.
        def symbolicReference = srProc.text.trim()
        assert !symbolicReference.isEmpty()
        gitCommit += "-$symbolicReference"
    }

    gitCommit
}

apply plugin: "com.github.kt3k.coveralls"
coveralls {
	sourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs).files.absolutePath
}

task jacocoRootReport(type: JacocoReport) {
    dependsOn = subprojects.jacocoTestReport
    sourceDirectories.setFrom(files(subprojects.sourceSets.main.allSource.srcDirs))
    classDirectories.setFrom(files(subprojects.sourceSets.main.output))
    executionData.setFrom(files(subprojects.jacocoTestReport.executionData))
    reports {
        xml.enabled true
        xml.destination file("${buildDir}/reports/jacoco/test/jacocoTestReport.xml")
    }
    // We could remove the following setOnlyIf line, but then
    // jacocoRootReport would silently be SKIPPED if something with
    // the projectsWithUnitTests is wrong (e.g. a project is missing
    // in there).
    setOnlyIf { true }
}

task javadocAll(type: Javadoc) {
    def currentJavaVersion = JavaVersion.current()
    if (currentJavaVersion.compareTo(JavaVersion.VERSION_1_9) >= 0) {
        options.addStringOption("-release", "8");
    }
    source subprojects.collect {project ->
        project.sourceSets.main.allJava }
    destinationDir = new File(buildDir, 'javadoc')
    // Might need a classpath
    classpath = files(subprojects.collect {project ->
        project.sourceSets.main.compileClasspath})
    options.linkSource = true
    options.use = true
    options.links = [
            "https://docs.oracle.com/javase/${sourceCompatibility.getMajorVersion()}/docs/api/",
    ] as String[]
}

if (JavaVersion.current().isJava8Compatible()) {
    tasks.withType(Javadoc) {
        // The '-quiet' as second argument is actually a hack,
        // since the one paramater addStringOption doesn't seem to
        // work, we extra add '-quiet', which is added anyway by
        // gradle. See https://github.com/gradle/gradle/issues/2354
        // See JDK-8200363 (https://bugs.openjdk.java.net/browse/JDK-8200363)
        // for information about the -Xwerror option.
        options.addStringOption('Xwerror', '-quiet')
    }
}

/**
 * Fetch sha256 checksums of artifacts published to maven central.
 *
 * Example: gradle -Prelease=1.3.13 mavenCentralChecksums
 */
task mavenCentralChecksums() {
    description 'Fetch and display checksums for artifacts published to Maven Central'
    String ver = project.hasProperty('release') ? release : shortVersion
    doLast {
        Process p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-core/${ver}/pgpainless-core-${ver}.jar.sha256".execute()
        if (p.waitFor() == 0) {
            print p.text.trim()
            println "  pgpainless-core/build/libs/pgpainless-core-${ver}.jar"
        }

        p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-sop/${ver}/pgpainless-sop-${ver}.jar.sha256".execute()
        if (p.waitFor() == 0) {
            print p.text.trim()
            println "  pgpainless-sop/build/libs/pgpainless-sop-${ver}.jar"
        }

        p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-cli/${ver}/pgpainless-cli-${ver}-all.jar.sha256".execute()
        if (p.waitFor() == 0) {
            print p.text.trim()
            println "  pgpainless-cli/build/libs/pgpainless-cli-${ver}-all.jar"
        }

        p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-cli/${ver}/pgpainless-cli-${ver}.jar.sha256".execute()
        if (p.waitFor() == 0) {
            print p.text.trim()
            println "  pgpainless-cli/build/libs/pgpainless-cli-${ver}.jar"
        }

        p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/hsregex/${ver}/hsregex-${ver}.jar.sha256".execute()
        if (p.waitFor() == 0) {
            print p.text.trim()
            println "  hsregex/build/libs/hsregex-${ver}.jar"
        }
    }
}