package de.arxsilex.maptools.converter.worker

import de.arxsilex.maptools.converter.core.GeoBounds
import de.arxsilex.maptools.converter.core.GeoRectangleRegion
import de.arxsilex.maptools.converter.core.GeoSelectionRegion
import java.nio.file.Files
import java.nio.file.Path

data class MapsforgeSourceRequest(
    val input: Path,
    val output: Path,
    val bounds: GeoBounds,
    val namespace: Int,
    val areas: List<GeoSelectionRegion> = listOf(GeoRectangleRegion(bounds)),
    val temporaryDirectory: Path = output.parent.resolve("maptools-temp"),
) {
    init {
        require(Files.isRegularFile(input)) { "Mapsforge-Eingabedatei nicht gefunden: $input" }
        require(input.toAbsolutePath().normalize() != output.toAbsolutePath().normalize()) {
            "Ein- und Ausgabedatei dürfen nicht identisch sein."
        }
        require(namespace in 0..999) { "Der Mapsforge-ID-Namensraum ist ungültig." }
        require(areas.isNotEmpty()) { "Mindestens ein Auswahlbereich ist erforderlich." }
        require(SelectionBoundsCodec.envelope(areas) == bounds) { "Die Auswahlhülle stimmt nicht mit den Teilbereichen überein." }
    }

    companion object {
        fun parse(arguments: Array<String>): MapsforgeSourceRequest {
            require(arguments.firstOrNull() == "mapsforge-source") {
                "Erwarteter Worker-Befehl: mapsforge-source"
            }
            val values = arguments.drop(1).chunked(2).associate { pair ->
                require(pair.size == 2 && pair[0].startsWith("--")) { "Ungültige Worker-Argumente." }
                pair[0].removePrefix("--") to pair[1]
            }
            fun required(name: String): String = values[name] ?: error("Worker-Argument --$name fehlt.")
            val areas = SelectionBoundsCodec.fromArguments(values)
            return MapsforgeSourceRequest(
                input = Path.of(required("input")).toAbsolutePath().normalize(),
                output = Path.of(required("output")).toAbsolutePath().normalize(),
                bounds = SelectionBoundsCodec.envelope(areas),
                namespace = required("namespace").toInt(),
                areas = areas,
                temporaryDirectory = Path.of(required("temp-dir")).toAbsolutePath().normalize(),
            )
        }
    }
}
