plugins {
    kotlin("multiplatform")
}

kotlin {
    jvm("desktop")
    jvmToolchain(25)

    sourceSets {
        named("desktopMain").dependencies {
            implementation("com.github.mapsforge.mapsforge:mapsforge-map-reader:0.29.0")
            implementation("org.apache.sis.storage:sis-geotiff:1.6")
        }
        commonTest.dependencies {
            implementation(kotlin("test"))
        }
    }
}

tasks.register<JavaExec>("inspectPbf") {
    group = "verification"
    description = "Liest den OSMHeader einer über -PpbfFile angegebenen PBF-Datei."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.pbf.PbfInspectorCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs("-Dfile.encoding=UTF-8", "-Dstdout.encoding=UTF-8", "-Dstderr.encoding=UTF-8")
    providers.gradleProperty("pbfFile").orNull?.let { pbfFile ->
        inputs.property("pbfFile", pbfFile)
        args(pbfFile)
    }
}

tasks.register<JavaExec>("scanPbf") {
    group = "verification"
    description = "Scannt alle Blöcke einer über -PpbfFile angegebenen PBF-Datei."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.pbf.PbfInspectorCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs("-Dfile.encoding=UTF-8", "-Dstdout.encoding=UTF-8", "-Dstderr.encoding=UTF-8")
    providers.gradleProperty("pbfFile").orNull?.let { pbfFile ->
        inputs.property("pbfFile", pbfFile)
        args("--scan", pbfFile)
        providers.gradleProperty("indexFile").orNull?.let { indexFile ->
            outputs.file(indexFile)
            args(indexFile)
        }
    }
}

tasks.register<JavaExec>("decodePbf") {
    group = "verification"
    description = "Dekodiert Nodes und Ways aller Datenblöcke einer PBF-Datei."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.pbf.PbfInspectorCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs(
        "-Xmx1g",
        "-Dfile.encoding=UTF-8",
        "-Dstdout.encoding=UTF-8",
        "-Dstderr.encoding=UTF-8",
    )
    providers.gradleProperty("pbfFile").orNull?.let { pbfFile ->
        inputs.property("pbfFile", pbfFile)
        args("--decode", pbfFile)
    }
}

tasks.register<JavaExec>("previewPbf") {
    group = "verification"
    description = "Erzeugt eine begrenzte Übersichtsvorschau aus einer PBF-Datei."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.pbf.PbfInspectorCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs(
        "-Xmx2g",
        "-Dfile.encoding=UTF-8",
        "-Dstdout.encoding=UTF-8",
        "-Dstderr.encoding=UTF-8",
    )
    providers.gradleProperty("pbfFile").orNull?.let { pbfFile ->
        inputs.property("pbfFile", pbfFile)
        args("--preview", pbfFile)
    }
}

tasks.register<JavaExec>("benchmarkPbf") {
    group = "verification"
    description = "Misst Blockscan und parallele PrimitiveBlock-Dekodierung einer PBF-Datei."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.pbf.ParallelPbfBenchmarkCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs(
        "-Xmx3g",
        "-Dfile.encoding=UTF-8",
        "-Dstdout.encoding=UTF-8",
        "-Dstderr.encoding=UTF-8",
    )
    providers.gradleProperty("pbfFile").orNull?.let { pbfFile ->
        inputs.file(pbfFile)
        args(pbfFile)
        val reportFile = providers.gradleProperty("benchmarkReport").orNull
            ?: layout.buildDirectory.file("reports/parallel-pbf-benchmark.json").get().asFile.absolutePath
        outputs.file(reportFile)
        args(reportFile)
        providers.gradleProperty("benchmarkThreads").orNull?.let { threadCount -> args(threadCount) }
    }
}

tasks.register<JavaExec>("buildMtci") {
    group = "verification"
    description = "Erzeugt MTCI-ID-Shards aus einer PBF-Datei."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.mtci.MtciBuilderCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs(
        "-Xmx3g",
        "-Dfile.encoding=UTF-8",
        "-Dstdout.encoding=UTF-8",
        "-Dstderr.encoding=UTF-8",
    )
    providers.gradleProperty("pbfFile").orNull?.let { pbfFile ->
        inputs.file(pbfFile)
        val outputDirectory = providers.gradleProperty("mtciOutput").orNull
            ?: layout.buildDirectory.dir("mtci/output").get().asFile.absolutePath
        outputs.dir(outputDirectory)
        args(pbfFile, outputDirectory)
        args(providers.gradleProperty("mtciShards").orNull ?: "64")
        args(providers.gradleProperty("mtciThreads").orNull ?: "16")
    }
}

tasks.register<JavaExec>("analyzeMtciSelection") {
    group = "verification"
    description = "Analysiert einen räumlichen Ausschnitt in vorhandenen MTCI-Shards."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.mtci.MtciSpatialCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs(
        "-Xmx3g",
        "-Dfile.encoding=UTF-8",
        "-Dstdout.encoding=UTF-8",
        "-Dstderr.encoding=UTF-8",
    )
    providers.gradleProperty("mtciDirectory").orNull?.let { directory ->
        args(directory)
        args(providers.gradleProperty("selectionWest").get())
        args(providers.gradleProperty("selectionSouth").get())
        args(providers.gradleProperty("selectionEast").get())
        args(providers.gradleProperty("selectionNorth").get())
        val report = providers.gradleProperty("selectionReport").orNull
            ?: layout.buildDirectory.file("reports/mtci-selection.json").get().asFile.absolutePath
        outputs.file(report)
        args(report)
        providers.gradleProperty("selectionOutputMtci").orNull?.let { outputDirectory ->
            outputs.dir(outputDirectory)
            args(outputDirectory)
        }
    }
}

tasks.register<JavaExec>("validateMtci") {
    group = "verification"
    description = "Prüft MTCI-IDs und sämtliche Way-/Relationsreferenzen."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.mtci.MtciValidateCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs("-Xmx3g", "-Dfile.encoding=UTF-8")
    providers.gradleProperty("mtciDirectory").orNull?.let { directory -> args(directory) }
}

tasks.register<JavaExec>("writeMtciPbf") {
    group = "verification"
    description = "Schreibt eine OSM-PBF direkt aus materialisierten MTCI-Shards."
    dependsOn("desktopMainClasses")
    mainClass.set("de.arxsilex.maptools.converter.core.pbf.MtciPbfWriterCliKt")
    classpath(
        layout.buildDirectory.dir("classes/kotlin/desktop/main"),
        configurations.named("desktopRuntimeClasspath"),
    )
    jvmArgs("-Xmx3g", "-Dfile.encoding=UTF-8")
    providers.gradleProperty("mtciDirectory").orNull?.let { directory ->
        args(directory, providers.gradleProperty("pbfOutput").get())
        args(providers.gradleProperty("selectionWest").get())
        args(providers.gradleProperty("selectionSouth").get())
        args(providers.gradleProperty("selectionEast").get())
        args(providers.gradleProperty("selectionNorth").get())
    }
}
