// Adapted from https://github.com/FabricMC/fabric/blob/31787236d242247e0b6c4ae806b1cfaa7042a62c/gradle/package-info.gradle, which is licensed under Apache 2.0.

import java.nio.file.Files

setupGeneratePackageInfos(sourceSets.main)

def setupGeneratePackageInfos(SourceSet sourceSet) {
	// We have to capture the source set name for the lazy string literals,
	// otherwise it'll just be whatever the last source set is in the list.
	def sourceSetName = sourceSet.name
	def taskName = sourceSet.getTaskName('generate', 'PackageInfos')
	def task = tasks.register(taskName, GeneratePackageInfosTask) {
		group = 'flywheel'
		description = "Generates package-info files for $sourceSetName packages."

		// Only apply to default source directory since we also add the generated
		// sources to the source set.
		sourceRoot = file("src/$sourceSetName/java")
		outputDir = file("src/$sourceSetName/generatedPackageInfos")
	}
	sourceSet.java.srcDir task

	def cleanTask = tasks.register(sourceSet.getTaskName('clean', 'PackageInfos'), Delete) {
		group = 'flywheel'
		delete file("src/$sourceSetName/generatedPackageInfos")
	}
	clean.dependsOn cleanTask
}

class GeneratePackageInfosTask extends DefaultTask {
	@SkipWhenEmpty
	@InputDirectory
	final DirectoryProperty sourceRoot = project.objects.directoryProperty()

	@OutputDirectory
	final DirectoryProperty outputDir = project.objects.directoryProperty()

	@TaskAction
	def run() {
		def output = outputDir.get().asFile.toPath()
		output.deleteDir()
		def root = sourceRoot.get().asFile.toPath()

		root.eachDirRecurse {
			def containsJava = Files.list(it).any {
				Files.isRegularFile(it) && it.fileName.toString().endsWith('.java')
			}

			if (containsJava && Files.notExists(it.resolve('package-info.java'))) {
				def relativePath = root.relativize(it)
				def target = output.resolve(relativePath)
				Files.createDirectories(target)

				target.resolve('package-info.java').withWriter {
					def packageName = relativePath.toString().replace(File.separator, '.')
					it.write("""@ParametersAreNonnullByDefault
					|@FieldsAreNonnullByDefault
					|@MethodsReturnNonnullByDefault
					|package $packageName;
					|
					|import javax.annotation.ParametersAreNonnullByDefault;
					|
					|import net.minecraft.FieldsAreNonnullByDefault;
					|import net.minecraft.MethodsReturnNonnullByDefault;
					|""".stripMargin())
				}
			}
		}
	}
}