import groovy.json.JsonOutput
import groovy.json.JsonSlurper

import java.util.concurrent.TimeUnit

plugins {
	id 'eclipse'
	id 'idea'
	id 'maven-publish'
	id 'net.minecraftforge.gradle' version '[6.0,6.2)'
	id 'org.parchmentmc.librarian.forgegradle' version '1.+'
	id 'org.spongepowered.mixin' version '0.7.+'
}

jarJar.enable()

/**
 * MAJORMOD.MAJORAPI.MINOR.PATCH
 * @return Hybrid Semantic Version
 */
private String getModVersion() {
	def snapshotVersion = System.getenv("SNAPSHOT_VERSION")

	if (snapshotVersion != null) {
		def parsedVersion = new JsonSlurper().parseText(file('mod_version.json').text)
		return parsedVersion.major + "." + snapshotVersion
	} else {
		def parsedVersion = new JsonSlurper().parseText(file('mod_version.json').text)
		return parsedVersion.major + "." + parsedVersion.semantic
	}
}

def mod_version = getModVersion()

version = "${mod_version}"
group = mod_group_id

base {
	archivesName = "${mod_id}-forge-${minecraft_version}"
}

java.toolchain.languageVersion = JavaLanguageVersion.of(17)

println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}"

sourceSets {
	main {
		resources {
			srcDir 'src/generated/resources' // Include resources generated by data generators
			exclude '.cache/'
		}
	}
	datagen {}
}

minecraft {
	mappings channel: mapping_channel, version: mapping_version

	// This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game.
	// It is REQUIRED to be set to true for this template to function.
	// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html
	copyIdeResources = true

	// When true, this property will add the folder name of all declared run configurations to generated IDE run configurations.
	// The folder name can be set on a run configuration using the "folderName" property.
	// By default, the folder name of a run configuration is the name of the Gradle project containing it.
	// generateRunFolders = true

	accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')

	runs {
		// applies to all run configurations
		configureEach {
			workingDirectory project.file('run')

			// Recommended logging data for a userdev environment
			// The markers can be added/remove as needed separated by commas.
			// "SCAN": For mods scan.
			// "REGISTRIES": For firing of registry events.
			// "REGISTRYDUMP": For getting the contents of all registries.
			property 'forge.logging.markers', 'REGISTRIES'

			// Recommended logging level for the console
			// You can set various levels here.
			// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
			property 'forge.logging.console.level', 'debug'

			property 'mixin.env.remapRefMap', 'true'
			property 'mixin.env.refMapRemappingFile', "${buildDir}/createSrgToMcp/output.srg"

			property 'geckolib.disable_examples', 'true'

			// Hot-Swapping via JBR, includes schema changes
			// https://forge.gemwire.uk/wiki/Hotswap#Applying_schema_changes
			jvmArgs '-XX:+IgnoreUnrecognizedVMOptions', '-XX:+AllowEnhancedClassRedefinition'

			mods {
				"${mod_id}" {
					source sourceSets.main
				}
			}
		}

		client {
			workingDirectory project.file('run/client')
			// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
			property 'forge.enabledGameTestNamespaces', mod_id
		}

		client2 {
			parent runs.client
			args '--username', 'Dev2'
		}

		server {
			workingDirectory project.file('run/server')

			property 'forge.enabledGameTestNamespaces', mod_id
			args '--nogui'
		}

		// This run config launches GameTestServer and runs all registered gametests, then exits.
		// By default, the server will crash when no gametests are provided.
		// The gametest system is also enabled by default for other run configs under the /test command.
		gameTestServer {
			property 'forge.enabledGameTestNamespaces', mod_id
		}

		data {
			workingDirectory project.file('run/data')

			// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
			args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')

			mods {
				"${mod_id}" {
					source sourceSets.main
					source sourceSets.datagen
				}
			}
		}
	}
}

mixin {
	add sourceSets.main, "mixins.biomancy.refmap.json"
	config 'mixins.biomancy.json'

	dumpTargetOnFailure = true
}

repositories {
	// ForgeGradle automatically adds the Forge maven and Maven Central

	// flatDir {
	//     dir 'libs'
	// }

	maven { url = "https://dvs1.progwml6.com/files/maven/" }  // JEI
	maven { url = "https://modmaven.k-4u.nl" }  // JEI backup
	maven {
		name = 'Geckolib'
		url = 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/'
		content {
			includeGroupByRegex("software\\.bernie.*")
			includeGroup("com.eliotlash.mclib")
		}
	}
	maven { url = 'https://maven.blamejared.com' }
	maven {
		url "https://dl.cloudsmith.io/public/klikli-dev/mods/maven/"
		content {
			includeGroup "com.klikli_dev"
		}
	}
	maven {
		name = 'tterrag maven'
		url = 'https://maven.tterrag.com/'
	}
	maven { url = "https://www.cursemaven.com" }
	maven { url = "https://api.modrinth.com/maven" }
	maven { url = "https://jitpack.io" }
}

configurations {
	datagenImplementation.extendsFrom minecraft
}

dependencies {
	minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"

	if (!Boolean.getBoolean("idea.sync.active")) {
		annotationProcessor "org.spongepowered:mixin:${mixin_version}:processor"
	}

	//TODO: remove when switching to NeoForge
	compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.3.5"))
	implementation(jarJar("io.github.llamalad7:mixinextras-forge:0.3.5")) {
		jarJar.ranged(it, "[0.3.5,)")
	}

	implementation fg.deobf("software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}")
	implementation("com.eliotlash.mclib:mclib:20")
	datagenImplementation fg.deobf("software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}")

	//https://h2database.com/html/mvstore.html
	minecraftLibrary(group: "com.h2database", name: "h2-mvstore", version: "2.2.224")
	jarJar(group: "com.h2database", name: "h2-mvstore", version: "[2.2.220,3.0.0)")

	compileOnly fg.deobf("com.klikli_dev:modonomicon-${minecraft_version}-common:${modonomicon_version}")
	implementation fg.deobf("com.klikli_dev:modonomicon-${minecraft_version}-forge:${modonomicon_version}")
	datagenCompileOnly fg.deobf("com.klikli_dev:modonomicon-${minecraft_version}-common:${modonomicon_version}")
	datagenImplementation fg.deobf("com.klikli_dev:modonomicon-${minecraft_version}-forge:${modonomicon_version}")

	compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}-common-api:${jei_version}")
	compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}") // compile against the JEI API but do not include it at runtime
	runtimeOnly fg.deobf("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") // at runtime, use the full JEI jar

	runtimeOnly fg.deobf("maven.modrinth:alexs-mobs:1.22.9")
	runtimeOnly fg.deobf("maven.modrinth:alexs-caves:2.0.2")
	runtimeOnly fg.deobf("maven.modrinth:citadel:2.6.0")
	datagenImplementation fg.deobf("maven.modrinth:alexs-mobs:1.22.9")
	datagenImplementation fg.deobf("maven.modrinth:alexs-caves:2.0.2")
	datagenImplementation fg.deobf("maven.modrinth:citadel:2.6.0")

	compileOnly fg.deobf("maven.modrinth:pehkui:3.7.12+1.20.1-forge")
	//needs to be compileOnly for datagen to work -> temporarily change to implementation for gameplay testing

//	implementation fg.deobf("se.mickelus.mutil:mutil:1.20.1-6.1.1")
	compileOnly fg.deobf("maven.modrinth:tetra:6.1.0")

//	runtimeOnly fg.deobf("maven.modrinth:parcool:1.20.1-3.2.1.2-R")

	datagenImplementation sourceSets.main.output
}

// This block of code expands all declared replace properties in the specified resource targets.
// A missing property will result in an error. Properties are expanded using ${} Groovy notation.
// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments.
// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html
tasks.named('processResources', ProcessResources).configure {
	var replaceProperties = [
			minecraft_version   : minecraft_version, minecraft_version_range: minecraft_version_range,
			forge_version       : forge_version, forge_version_range: forge_version_range,
			loader_version_range: loader_version_range,

			mod_id              : mod_id,
			mod_name            : mod_name,
			mod_license         : mod_license,
			mod_version         : mod_version,
			mod_authors         : mod_authors,
			mod_credits         : mod_credits,
			mod_description     : mod_description,

			geckolib_version    : geckolib_version, geckolib_version_range: geckolib_version_range,
			jei_version: jei_version, jei_version_range: jei_version_range
	]
	inputs.properties replaceProperties

	filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) {
		expand replaceProperties + [project: project]
	}

	exclude '**/*.psd'
	exclude '**/*.bbmodel'
	exclude '**/*.pdn'

	doLast {
		minifyJsons(processResources.outputs.files.asPath)
	}
}

private void minifyJsons(String fdir) {
	print "minmizing jsons..."
	long startTime = System.nanoTime()
	for (File file in fileTree(dir: fdir, include: "**/*.json")) {
		try {
			file.text = JsonOutput.toJson(new JsonSlurper().parse(file))
		} catch (Exception e) {
			throw new Exception("Failed to minimize " + file, e)
		}
	}
	long ms = TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS)
	printf "%7s sec, %s ms \n", (int) (ms / 1000), ms % 1000
}

tasks.jarJar.configure {
	archiveClassifier = ''
	from { ["CREDITS.md", "LICENSE.txt", "3RD_PARTY_LICENSE.txt"] } //copy files from the repository root into the jar

	finalizedBy 'reobfJarJar'
}

tasks.named('jar', Jar).configure {
	archiveClassifier = "slim"

	manifest {
		attributes([
				'Specification-Title'     : mod_id,
				'Specification-Vendor'    : mod_vendor,
				'Specification-Version'   : '2',
				'Implementation-Title'    : project.name,
				'Implementation-Version'  : project.jar.archiveVersion,
				'Implementation-Vendor'   : mod_vendor,
				'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
				'MixinConfigs'            : "mixins.biomancy.json"
		])
	}

	from { ["CREDITS.md", "LICENSE.txt"] } //copy files from the repository root into the jar

	finalizedBy 'reobfJar'
}

tasks.build.configure {
	dependsOn 'jarJar'
}

publishing {
	publications {
		register('mavenJava', MavenPublication) {
			artifact jar
		}
	}
	repositories {
		maven {
			url "file://${project.projectDir}/mcmodsrepo"
		}
	}
}

tasks.withType(JavaCompile).configureEach {
	options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
