import org.ajoberstar.grgit.Grgit
import org.gradle.util.VersionNumber

plugins {
    alias libs.plugins.bnd apply false
    alias libs.plugins.android.library apply false
    alias libs.plugins.errorprone
    alias libs.plugins.grgit
    alias libs.plugins.osdetector
    alias libs.plugins.task.tree
}

subprojects {
    def androidProject = ((project.name == 'conscrypt-android')
            || (project.name == 'conscrypt-android-platform')
            || (project.name == 'conscrypt-benchmark-android')
            || (project.name == 'conscrypt-benchmark-caliper'))
    if (androidProject) {
        repositories {
            google()
        }
    } else {
        apply plugin: 'java-library'
        apply plugin: 'cpp'

        model {
            toolChains {
                visualCpp(VisualCpp)
                // Prefer Clang over Gcc (order here matters!)
                clang(Clang) {
                    // Gradle 7.x still seems to get confused about toolchains on Mac
                    // so explicitly add -arch args.
                    target("osx_aarch64") {
                        cppCompiler.withArguments { args ->
                            args << "-arch" << "arm64"
                        }
                        linker.withArguments { args ->
                            args << "-arch" << "arm64"
                        }
                    }
                    target("osx_x86-64") {
                        cppCompiler.withArguments { args ->
                            args << "-arch" << "x86_64"
                        }
                        linker.withArguments { args ->
                            args << "-arch" << "x86_64"
                        }
                    }
                }
                gcc(Gcc)
            }
        }
    }
    apply plugin: "jacoco"
    apply plugin: libs.plugins.errorprone.get().pluginId

    group = "org.conscrypt"
    description = 'Conscrypt is an alternate Java Security Provider that uses BoringSSL'
    version = "2.6-SNAPSHOT"

    ext {
        // Needs to be binary compatible with androidMinSdkVersion
        androidMinJavaVersion = JavaVersion.VERSION_1_8

        if (project.hasProperty("boringsslHome")) {
            boringsslHome = project.property("boringsslHome")
        } else {
            boringsslHome = "$System.env.BORINGSSL_HOME"
        }
        boringsslIncludeDir = normalizePath("$boringsslHome/include")

        // Ensure the environment is configured properly.
        assert file("$boringsslIncludeDir").exists()

        // Get the commit hash for BoringSSL.
        boringSslGit = Grgit.open(dir: boringsslHome)
        boringSslVersion = boringSslGit.head().id

        signJar = { jarPath ->
            if (rootProject.hasProperty('signingKeystore') && rootProject.hasProperty('signingPassword')) {
                def command = 'jarsigner -keystore ' + rootProject.signingKeystore +
                        ' -storepass ' + rootProject.signingPassword +
                        ' ' + jarPath + ' signingcert'
                def process = command.execute()
                process.waitFor()
                if (process.exitValue()) {
                    throw new RuntimeException('Jar signing failed for ' + jarPath + ': ' + process.text)
                }
            }
        }
    }

    repositories {
        mavenCentral()
        mavenLocal()
    }

    jacoco {
        toolVersion = libs.versions.jacoco
    }

    configurations {
        jacocoAnt
        jacocoAgent
    }

    dependencies {
        jacocoAnt libs.jacoco.ant
        jacocoAgent libs.jacoco.agent
    }

    dependencies {
        errorprone libs.errorprone
    }

    tasks.register("generateProperties", WriteProperties) {
        ext {
            parsedVersion = VersionNumber.parse(version)
        }
        property("org.conscrypt.version.major", parsedVersion.getMajor())
        property("org.conscrypt.version.minor", parsedVersion.getMinor())
        property("org.conscrypt.version.patch", parsedVersion.getMicro())
        property("org.conscrypt.boringssl.version", boringSslVersion)
        outputFile "build/generated/resources/org/conscrypt/conscrypt.properties"
    }

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

        [tasks.named("compileJava"), tasks.named("compileTestJava")].forEach { t ->
            t.configure {
                options.compilerArgs += ["-Xlint:all", "-Xlint:-options", '-Xmaxwarns', '9999999']
                options.encoding = "UTF-8"
                options.release = 8

                if (rootProject.hasProperty('failOnWarnings') && rootProject.failOnWarnings.toBoolean()) {
                    options.compilerArgs += ["-Werror"]
                }
            }
        }

        tasks.named("compileTestJava").configure {
            // serialVersionUID is basically guaranteed to be useless in our tests
            options.compilerArgs += ["-Xlint:-serial"]
        }

        tasks.named("jar").configure {
            manifest {
                attributes('Implementation-Title': name,
                        'Implementation-Version': archiveVersion,
                        'Built-By': System.getProperty('user.name'),
                        'Built-JDK': System.getProperty('java.version'),
                        'Source-Compatibility': sourceCompatibility,
                        'Target-Compatibility': targetCompatibility)
            }
        }

        javadoc.options {
            encoding = 'UTF-8'
            links 'https://docs.oracle.com/en/java/javase/21/docs/api/java.base/'
        }

        tasks.register("javadocJar", Jar) {
            archiveClassifier = 'javadoc'
            from javadoc
        }

        tasks.register("sourcesJar", Jar) {
            archiveClassifier = 'sources'
            from sourceSets.main.allSource
        }

        // At a test failure, log the stack trace to the console so that we don't
        // have to open the HTML in a browser.
        test {
            testLogging {
                exceptionFormat = 'full'
                showExceptions true
                showCauses true
                showStackTraces true
                showStandardStreams = true
            }
            // Enable logging for all conscrypt classes while running tests.
            systemProperty 'java.util.logging.config.file', "${rootDir}/test_logging.properties"
            maxHeapSize = '1500m'
        }
    }
}

static String normalizePath(path) {
    new File(path.toString()).absolutePath
}
