buildscript {
    dependencies {
        def kotlinVersion = file("generated/kotlin_version.txt").text
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
    }
}

plugins {
    id 'fabric-loom' version '1.9.1'
    id 'maven-publish'
    id "com.diffplug.spotless" version "6.19.0"
    id 'me.modmuss50.mod-publish-plugin' version '0.8.1'
}

apply plugin: "org.jetbrains.kotlin.jvm"

group = project.group

def ENV = System.getenv()
def LIBRARY_VERSIONS_FILE = "generated/library_versions.json"
def KOTLIN_VERSION_FILE = "generated/kotlin_version.txt"

def kotlinLib = "org.jetbrains.kotlin:kotlin-stdlib"
def libraries = [
        kotlinLib,
        "org.jetbrains.kotlin:kotlin-stdlib-jdk8",
        "org.jetbrains.kotlin:kotlin-stdlib-jdk7",
        "org.jetbrains.kotlin:kotlin-reflect",

        "org.jetbrains.kotlinx:kotlinx-coroutines-core",
        "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm",
        "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8",
        "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm",
        "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm",
        "org.jetbrains.kotlinx:kotlinx-serialization-cbor-jvm",
        "org.jetbrains.kotlinx:atomicfu-jvm",
        "org.jetbrains.kotlinx:kotlinx-datetime-jvm",
        "org.jetbrains.kotlinx:kotlinx-io-core-jvm",
        "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm"
]

def libVersions = new JsonSlurper().parse(file(LIBRARY_VERSIONS_FILE))
def hasMissingLibVersion = !libVersions.keySet().containsAll(libraries)
def kotlinVersion = file(KOTLIN_VERSION_FILE).text

println("Kotlin: ${kotlinVersion}")
println("Libraries:")
libVersions.forEach { k, v ->
    println("\t${k}:${v}")
}

version = "${project.modVersion}+kotlin.${kotlinVersion}" + (ENV.GITHUB_ACTIONS ? "" : ".local")

loom {
    mods {
        flk {
            sourceSet sourceSets.main
        }
    }
}

configurations {
    includeAndExpose

    modApi {
        extendsFrom includeAndExpose
    }
    include {
        extendsFrom includeAndExpose
    }
}

configurations.all {
    resolutionStrategy {
        failOnNonReproducibleResolution()
    }
}

dependencies {
    minecraft "com.mojang:minecraft:${project.minecraftVersion}"
    mappings "net.fabricmc:yarn:${project.mappingsVersion}:v2"
    modImplementation "net.fabricmc:fabric-loader:${project.loaderVersion}"
	testImplementation "net.fabricmc:fabric-loader-junit:${project.loaderVersion}"
	testImplementation "org.jetbrains.kotlin:kotlin-test"

    if (hasMissingLibVersion) {
        println("Contains missing library version, run updateLibraryVersions task!")
    } else {
        libraries.forEach {
            includeAndExpose("${it}:${libVersions[it]}")
        }
    }
}

processResources {
    inputs.property "version", project.version

    filesMatching("fabric.mod.json") {
        expand "version": project.version
    }
}

tasks.withType(JavaCompile).configureEach {
    it.options.release = 8
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

java {
    withSourcesJar()
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

spotless {
    kotlin {
        licenseHeaderFile(rootProject.file("HEADER"))
    }
}

jar {
    from("LICENSE") {
        rename { "${it}_${project.base.archivesName.get()}" }
    }
}

test {
	useJUnitPlatform()
	afterEvaluate {
		// See: https://github.com/FabricMC/fabric-loader/pull/585
		def classPathGroups = loom.mods.stream()
			.map { modSettings ->
				net.fabricmc.loom.util.gradle.SourceSetHelper.getClasspath(modSettings, getProject()).stream()
					.map(File.&getAbsolutePath)
					.collect(java.util.stream.Collectors.joining(File.pathSeparator))
			}
			.collect(java.util.stream.Collectors.joining(File.pathSeparator+File.pathSeparator))

		systemProperty("fabric.classPathGroups", classPathGroups)
	}
}

task processMDTemplates(type: Copy) {
    group = "documentation"
    doFirst {
        if (hasMissingLibVersion) {
            throw new GradleException("Contains missing library version, run updateLibraryVersions task first!")
        }
    }

    from(file("templates"))
    include("**/*.template.md")
    filesMatching("**/*.template.md") {
        name = sourceName.replace("template.", "")
        def template = [
                MOD_VERSION   : "${project.modVersion}+kotlin.${kotlinVersion}",
                LOADER_VERSION: project.loaderVersion
        ]
        libraries.forEach {
            def key = it.split(":", 2)[1].replace("-", "_").toUpperCase(Locale.ROOT) + "_VERSION"
            template.put(key, libVersions[it])
        }
        expand(template)
    }
    destinationDir = rootDir
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            groupId = project.group
            artifactId = project.name.toLowerCase()
            version = project.version

            from components.java
        }
    }

    repositories {
        if (ENV.MAVEN_URL) {
            maven {
                url ENV.MAVEN_URL
                credentials {
                    username ENV.MAVEN_USERNAME
                    password ENV.MAVEN_PASSWORD
                }
            }
        }
    }
}

publishMods {
    file = remapJar.archiveFile
    changelog = ENV.CHANGELOG ?: "No changelog provided"
    type = STABLE
    displayName = "Fabric Language Kotlin ${project.version}"
    modLoaders.add("fabric")
    dryRun = ENV.GITHUB_TOKEN == null

    curseforge {
        accessToken = providers.environmentVariable("CURSEFORGE_API_KEY")
        projectId = "308769"
        minecraftVersionRange {
			start = "1.14"
			end = "latest"
		}
    }
    modrinth {
        accessToken = providers.environmentVariable("MODRINTH_TOKEN")
        projectId = "Ha28R6CL"
		minecraftVersionRange {
			start = "1.14"
			end = "latest"
		}
    }
    github {
        accessToken = providers.environmentVariable("GITHUB_TOKEN")
        repository = ENV.CI != null ? providers.environmentVariable("GITHUB_REPOSITORY") : "FabricMC/dryrun"
        commitish = ENV.CI != null ? getBranch() : "dryrun"
    }
}

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.xml.XmlSlurper
import org.gradle.util.VersionNumber

import java.nio.charset.StandardCharsets

static def getBranch() {
    def ENV = System.getenv()
    if (ENV.GITHUB_REF) {
        def branch = ENV.GITHUB_REF
        return branch.substring(branch.lastIndexOf("/") + 1)
    }

    throw new RuntimeException("Unable to get branch")
}

// A task to ensure that the version being released has not already been released.
task checkVersion {
    doFirst {
        def xml = new URL("https://maven.fabricmc.net/net/fabricmc/fabric-language-kotlin/maven-metadata.xml").text
        def metadata = new XmlSlurper().parseText(xml)
        def versions = metadata.versioning.versions.version*.text()
        if (versions.contains(version)) {
            throw new RuntimeException("${version} has already been released!")
        }
    }
}

task updateLibraryVersions {
    group = "update"
    doFirst {
        def output = [:]
        def slurper = new XmlSlurper()
        for (def lib : libraries) {
            def split = lib.split(":", 2)
            def group = split[0].replace(".", "/")
            def artifact = split[1]
            def xml = new URL("https://repo1.maven.org/maven2/${group}/${artifact}/maven-metadata.xml").text
            def metadata = slurper.parseText(xml)
            def versions = metadata.versioning.versions.version*.text()

            def latest = versions[0]
            def latestParsed = VersionNumber.parse(latest)
            for (def version : versions) {
                def parsed = VersionNumber.parse(version)
                if (parsed.qualifier == null && parsed > latestParsed) {
                    latestParsed = parsed
                    latest = version
                }
            }

            println("${lib} = ${latest}")
            output.put(lib, latest)

            if (lib == kotlinLib) {
                file(KOTLIN_VERSION_FILE).setText(latest, StandardCharsets.UTF_8.name())
            }
        }
        def json = new JsonBuilder(output)
        file(LIBRARY_VERSIONS_FILE).setText(json.toPrettyString(), StandardCharsets.UTF_8.name())
    }
}

task updateVersions {
    group = "update"
    dependsOn(updateLibraryVersions)
}

tasks.publishMods.dependsOn checkVersion
publish.dependsOn checkVersion
