import com.badlogic.gdx.tools.texturepacker.TexturePacker
import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.gradle.work.Incremental
import org.gradle.work.InputChanges
import java.io.File
import java.util.*

import java.util.regex.Pattern
import kotlin.collections.HashSet

abstract class TexturePackerTask : DefaultTask() {
    @get:Incremental
    @get:InputDirectory
    abstract val input : DirectoryProperty

    @get:OutputDirectory
    abstract val resourceOutput : DirectoryProperty

    @get:OutputDirectory
    abstract val generatedSourceOutput : DirectoryProperty

    @TaskAction
    fun pack(changes: InputChanges) {
        val dirs = HashSet<File>()
        val inputDir = input.asFile.get()

        if (changes.isIncremental) {
            val root = inputDir.toPath()
            for (change in changes.getFileChanges(input)) {
                if (!change.file.isFile) continue
                dirs.add(root.resolve(root.relativize(change.file.toPath()).subpath(0, 1)).toFile())
            }
        } else {
            inputDir.listFiles()?.filter { it.isDirectory }?.forEach { dirs.add(it) }
        }

        val outputDir = resourceOutput.get().asFile
        for (dir in dirs) {
            TexturePacker.process(dir.path, outputDir.path, dir.name)

            val atlas = File(outputDir, dir.name + ".atlas")
            if (atlas.exists()) {
                val name = dir.name[0].uppercaseChar() + dir.name.substring(1) + "Atlas"
                val path = outputDir.toPath().relativize(atlas.toPath()).toString()

                val builder = StringBuilder()
                builder.append("""
                    package eu.jonahbauer.wizard.client.libgdx;
                    public class $name {
                        public static final String ${'$'}PATH = "$path";
                    
                """.trimIndent())

                val content = atlas.readText(Charsets.UTF_8)
                val matcher = Pattern.compile("(?m)^([^:]*?)\$\\n {2}").matcher(content)
                val fields = HashSet<String>()
                while (matcher.find()) {
                    val texture = matcher.group(1)
                    val field = texture.replace("-", "_").replace("/", "_").uppercase(Locale.ROOT)
                    fields.add("    public static final String $field = \"$texture\";\n")
                }

                fields.forEach(builder::append)
                builder.append("}\n")

                val out = generatedSourceOutput.file("eu/jonahbauer/wizard/client/libgdx/${name}.java").get().asFile
                out.parentFile.mkdirs()
                out.writeText(builder.toString(), Charsets.UTF_8)
            }
        }
    }
}