package de.arxsilex.maptools.converter.worker

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

data class PoiMergeSource(val path: Path, val schema: PoiSchemaVersion)

data class PoiMergeRequest(
    val sources: List<PoiMergeSource>,
    val output: Path,
    val targetSchema: PoiSchemaVersion,
    val temporaryDirectory: Path,
    val areas: List<GeoSelectionRegion>,
) {
    init {
        require(sources.isNotEmpty()) { "Mindestens eine POI-Eingabedatei ist erforderlich." }
        sources.forEach { require(Files.isRegularFile(it.path)) { "POI-Eingabedatei nicht gefunden: ${it.path}" } }
        require(areas.isNotEmpty()) { "Mindestens ein POI-Auswahlbereich ist erforderlich." }
        require(sources.none { it.path.toAbsolutePath().normalize() == output.toAbsolutePath().normalize() }) {
            "POI-Eingabe und -Ausgabe müssen verschieden sein."
        }
    }

    companion object {
        fun parse(arguments: Array<String>): PoiMergeRequest {
            require(arguments.firstOrNull() == "poi-merge") { "Erwarteter Worker-Befehl: poi-merge" }
            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 schemas = pairs.filter { it[0] == "--source-schema" }.map { schema(it[1]) }
            require(inputs.size == schemas.size) { "Jede POI-Eingabe benötigt genau eine Schemaversion." }
            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 PoiMergeRequest(
                sources = inputs.zip(schemas) { path, sourceSchema -> PoiMergeSource(path, sourceSchema) },
                output = output,
                targetSchema = schema(required("target-schema")),
                temporaryDirectory = values["temp-dir"]?.let(Path::of)?.toAbsolutePath()?.normalize()
                    ?: output.parent.resolve(".maptools-temp"),
                areas = SelectionBoundsCodec.fromArguments(values),
            )
        }

        private fun schema(value: String): PoiSchemaVersion = PoiSchemaVersion.entries.single {
            it.metadataVersion == value.toInt()
        }
    }
}
