import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.gradle.DokkaTask
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import java.net.URI

/*
 * STAROPENSOURCE ENGINE SOURCE FILE
 * Copyright (c) 2024 The StarOpenSource Engine Authors
 * Licensed under the GNU Affero General Public License v3
 * with an exception allowing classpath linking.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

// Buildscript
buildscript {
    // Repositories
    repositories {
        mavenLocal()
        mavenCentral()
        gradlePluginPortal()
    }
}

// Plugins
plugins {
    id("java-library")
    id("maven-publish")

    // Kotlin support
    id("org.jetbrains.kotlin.jvm") version("2.0.0")

    // Dokka
    id("org.jetbrains.dokka") version("1.9.20")

    // Git properties
    id("com.gorylenko.gradle-git-properties") version("2.4.2")
}

allprojects {
    // Plugins
    apply(plugin = "java")
    apply(plugin = "java-library")
    apply(plugin = "maven-publish")
    apply(plugin = "org.jetbrains.kotlin.jvm")
    apply(plugin = "org.jetbrains.dokka")
    apply(plugin = "com.gorylenko.gradle-git-properties")

    // Version
    version = "${property("versionRelease") as String}-${property("versionType") as String}${property("versionTyperelease") as String}"
    if (property("versionFork") != "")
        version = "${version as String}-${property("versionFork") as String}"
    if (property("versionCompanion") != "")
        version = "${version as String}+${property("versionCompanion") as String}"

    // Repositories
    repositories {
        mavenLocal()
        mavenCentral()
    }

    // Dependencies
    dependencies {
        // Kotlin support
        kotlin(property("dependencyKotlinStdIdentifier") as String)
        kotlin(property("dependencyKotlinStdJavaIdentifier") as String)
        implementation("${property("dependencyKotlinReflectIdentifier") as String}:${property("dependencyKotlinReflectVersion") as String}")
        implementation("${property("dependencyKotlinDateTimeIdentifier") as String}:${property("dependencyKotlinDateTimeVersion") as String}")

        // OSHI
        implementation("${property("dependencyOshiIdentifier") as String}:${property("dependencyOshiVersion") as String}")

        // Unit testing
        // -> Kotlin
        testImplementation(kotlin("test"))
        // -> JUnit
        testImplementation(platform("${property("testDependencyJUnitBOMIdentifier")}:${property("testDependencyJUnitVersion")}"))
        testImplementation("${property("testDependencyJUnitJupiterIdentifier")}")
        testRuntimeOnly("${property("testDependencyJUnitPlatformLauncherIdentifier")}")
        // -> sos!engine
        testImplementation(project(":testing"))
    }

    // Java
    java {
        // Java version
        sourceCompatibility = JavaVersion.valueOf("VERSION_${property("java") as String}")
        targetCompatibility = JavaVersion.valueOf("VERSION_${property("java") as String}")

        if (!(hasProperty("java.skipToolchainSpecification") && property("java.skipToolchainSpecification") as String == "true"))
            toolchain {
                languageVersion = JavaLanguageVersion.of(property("java") as String)
            }
    }

    // Kotlin
    kotlin.compilerOptions {
        // Configuration
        progressiveMode = true
        allWarningsAsErrors = true
        verbose = true

        // Set target metadata
        jvmTarget = JvmTarget.valueOf("JVM_${property("java") as String}")
    }

    // Dokka
    // -> Register jar generation tasks
    //    See https://kotlinlang.org/docs/dokka-gradle.html#build-javadoc-jar
    tasks.register<Jar>("dokkaHtmlJar") {
        dependsOn(tasks.dokkaHtml)
        from(tasks.dokkaHtml.flatMap { it.outputDirectory })
        archiveClassifier.set("html-docs")
    }

    tasks.register<Jar>("dokkaJavadocJar") {
        dependsOn(tasks.dokkaJavadoc)
        from(tasks.dokkaJavadoc.flatMap { it.outputDirectory })
        archiveClassifier.set("javadoc")
    }

    // -> Configure Dokka
    tasks.withType<DokkaTask>().configureEach {
        // Styling
        val dokkaBaseConfiguration = """
        {
          "_customAssets": ["${file("assets/my-image.png")}"],
          "_customStyleSheets": ["${file("assets/my-styles.css")}"],
          "footerMessage": "&copy; 2024 The StarOpenSource Engine Authors. Licensed under the GNU Affero General Public License v3",
          "_separateInheritedMembers": false,
          "_templatesDir": "${file("dokka/templates")}",
          "_mergeImplicitExpectActualDeclarations": false
        }
        """

        pluginsMapConfiguration = mapOf(
            "org.jetbrains.dokka.base.DokkaBase" to dokkaBaseConfiguration
        )

        // Configuration
        moduleName = rootProject.name
        moduleVersion = "v" + rootProject.version as String
        failOnWarning = true
        suppressObviousFunctions = true
        suppressInheritedMembers = true

        dokkaSourceSets.configureEach {
            // Metadata
            displayName = project.name
            documentedVisibilities = setOf(DokkaConfiguration.Visibility.PUBLIC, DokkaConfiguration.Visibility.PROTECTED)
            reportUndocumented = false
            skipEmptyPackages = false
            skipDeprecated = false
            jdkVersion = 21

            // Source link
            sourceLink {
                localDirectory = projectDir.resolve("src")
                remoteUrl = URI("https://git.staropensource.de/StarOpenSource/Engine/src/branch/develop/" + project.name.replace(":", "/") + "/src").toURL()
                remoteLineSuffix = "#L"
            }
        }
    }

    // Unit testing
    // -> Configure Gradle to use JUnit
    tasks.test {
        useJUnitPlatform()

        testLogging {
            events(
                "passed",
                "skipped",
                "failed"
            )
        }
        maxParallelForks = 1
    }
}