package de.arxsilex.maptools.converter.worker

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

data class ElevationRequest(
    val inputs: List<Path>,
    val output: Path,
    val outputFormat: ElevationOutputFormat,
    val temporaryDirectory: Path,
    val areas: List<GeoSelectionRegion>,
) {
    init {
        require(inputs.isNotEmpty()) { "Mindestens eine Höhendatenquelle ist erforderlich." }
        inputs.forEach { require(Files.isRegularFile(it)) { "Höhendatenquelle nicht gefunden: $it" } }
        require(areas.isNotEmpty()) { "Mindestens ein Auswahlbereich ist erforderlich." }
        require(inputs.none { it.toAbsolutePath().normalize() == output.toAbsolutePath().normalize() }) {
            "Ein- und Ausgabe dürfen nicht identisch sein."
        }
    }

    companion object {
        fun parse(arguments: Array<String>): ElevationRequest {
            require(arguments.firstOrNull() == "elevation") { "Erwarteter Worker-Befehl: elevation" }
            val pairs = arguments.drop(1).chunked(2).also { chunks ->
                require(chunks.all { it.size == 2 && it[0].startsWith("--") }) {
                    "Ungültige Worker-Argumente."
                }
            }
            val inputs = pairs.filter { it[0] == "--input" }
                .map { Path.of(it[1]).toAbsolutePath().normalize() }
            val values = pairs.associate { it[0].removePrefix("--") to it[1] }
            fun required(name: String): String = values[name] ?: error("Worker-Argument --$name fehlt.")
            val output = Path.of(required("output")).toAbsolutePath().normalize()
            return ElevationRequest(
                inputs = inputs,
                output = output,
                outputFormat = ElevationOutputFormat.valueOf(required("format")),
                temporaryDirectory = values["temp-dir"]?.let(Path::of)?.toAbsolutePath()?.normalize()
                    ?: output.parent.resolve(".maptools-temp"),
                areas = SelectionBoundsCodec.fromArguments(values),
            )
        }
    }
}
