/*
 * STAROPENSOURCE ENGINE SOURCE FILE
 * Copyright (c) 2024 The StarOpenSource Engine Authors
 * Licensed under the GNU General Public License v3.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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/>.
 */

import ca.solostudios.nyx.util.reposiliteMaven
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.gradle.DokkaTask
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/>.
 */

// 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")

    // Nyx
    // Smol props to the creator of this plugin!
    // solonovamax helped me (JeremyStarTM) improve
    // this build script.
    id("ca.solo-studios.nyx") version("0.2.3")
}

allprojects {
    // Plugins
    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")
    apply(plugin = "ca.solo-studios.nyx")

    nyx {
        // Project information
        info {
            group = "de.staropensource.engine"
            version = buildString {
                append(property("versionRelease") as String)
                append("-")
                append(property("versionType") as String)
                append(property("versionTyperelease") as String)

                if (property("versionFork") != "") {
                    append(version)
                    append("-")
                    append(property("versionFork") as String)
                }

                if (property("versionCompanion") != "") {
                    append(version)
                    append("-")
                    append(property("versionCompanion") as String)
                }
            }
            description = this@allprojects.description ?: "The description of this sos!engine subsystem or subproject was not set"
            organizationName = "The StarOpenSource Project"
            organizationUrl = "hhttps://staropensource.de"
            developer {
                id = "staropensource"
                name = "The StarOpenSource Project"
                email = "support@staropensource.de"
                url = "https://staropensource.de"
            }
            repository.fromGitHostWithIssues("StarOpenSource", "Engine", "https://git.staropensource.de", "sos!git")
            license.useGPLv3()
        }

        // Publishing
        publishing {
            withPublish()
            repositories {
                reposiliteMaven("https://mvn.staropensource.de/engine") {
                    name = "staropensource-engine"
                    credentials(PasswordCredentials::class)
                }
            }
        }

        // Compilation
        compile {
            withAllWarnings()
            withWarningsAsErrors()
            withDistributeLicense()
            encoding = "UTF-8"
            withZip64()
            withSuppressWarnings()
            jvmToolchain = (property("languageJava") as String).toInt()
            jvmTarget = (property("languageJava") as String).toInt()
            withSourcesJar()
            withJavadocJar()
            withReproducibleBuilds()

            // Kotlin-specific settings
            kotlin {
                apiVersion = property("languageKotlin") as String
                languageVersion = property("languageKotlin") as String
                compilerArgs = listOf(
                    "-progressive"
                )
            }
        }
    }

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

    // Dependencies
    dependencies {
        // Kotlin support
        implementation("${property("dependencyKotlin_ReflectIdentifier") as String}:${property("dependencyKotlinVersion") as String}")
        implementation("${property("dependencyKotlin_CoroutinesIdentifier") as String}:${property("dependencyKotlin_CoroutinesVersion") as String}")
        implementation("${property("dependencyKotlin_DateTimeIdentifier") as String}:${property("dependencyKotlin_DateTimeVersion") as String}")

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

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

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

    // 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${this@allprojects.version as String}"
        failOnWarning = true
        suppressObviousFunctions = true
        suppressInheritedMembers = true

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

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

    // Git properties
    // -> Configure
    gitProperties {
        dotGitDirectory = file("${rootProject.rootDir}/.git")
        failOnNoGitDirectory = false  // Allow continuing if .git directory is missing (tarball)
        extProperty = "git"
        dateFormat = "yyyy-MM-dd'T'HH:mm:ss.S'Z'"
        dateFormatTimeZone = "UTC"
    }

    // -> Copy task
    tasks.register("copyGitProperties") {
        dependsOn(tasks.generateGitProperties)
        inputs.file("${this@allprojects.projectDir}/build/resources/main/git.properties")

        doLast {
            if (rootProject == this@allprojects)
                return@doLast

            file(inputs.files.first())
                .copyTo(
                    file("${this@allprojects.projectDir}/src/main/resources/sosengine-${this@allprojects.name.replace(":", "-")}-git.properties"),
                    overwrite = true
                )
        }
    }
    tasks.processResources {
        dependsOn(tasks["copyGitProperties"])
    }

    // Gradle properties
    // -> Copy task
    tasks.register("copyGradleProperties") {
        inputs.file("${rootProject.projectDir.path}/gradle.properties")

        doLast {
            if (rootProject == project)
                return@doLast

            file(inputs.files.first())
                .copyTo(
                    file("${this@allprojects.projectDir}/src/main/resources/sosengine-${this@allprojects.name.replace(":", "-")}-gradle.properties"),
                    overwrite = true
                )
        }
    }
    tasks.processResources {
        dependsOn(tasks["copyGradleProperties"])
    }
}