package de.arxsilex.maptools.converter.desktop

import de.arxsilex.maptools.converter.core.ExportSelection
import java.nio.file.Path

internal data class ExportTargets(
    val mapsforgeMap: Path?,
    val mapsforgePoi: Path?,
    val filteredPbf: Path?,
    val elevationData: Path?,
) {
    val all: List<Path> = listOfNotNull(mapsforgeMap, mapsforgePoi, filteredPbf, elevationData)

    fun sourceConflicts(sources: Iterable<Path>): List<Path> {
        val normalizedSources = sources
            .mapTo(HashSet()) { it.toAbsolutePath().normalize() }
        return all.filter { it.toAbsolutePath().normalize() in normalizedSources }
    }

    companion object {
        fun suggestedBaseName(
            sourceBaseName: String,
            fullFile: Boolean,
            selection: ExportSelection,
        ): String {
            require(sourceBaseName.isNotBlank()) { "Der Quelldateiname ist ungültig." }
            val parts = buildList {
                add(sourceBaseName)
                add(if (fullFile) "konvertiert" else "ausschnitt")
                if (selection.mapsforgeMap) {
                    add("mapv${selection.mapFormatVersion.metadataVersion}")
                }
                if (selection.mapsforgePoi) {
                    add("poiv${selection.poiSchemaVersion.metadataVersion}")
                }
                if (selection.elevationData) {
                    add("dem-${selection.elevationOutputFormat.name.lowercase().replace('_', '-')}")
                }
            }
            return parts.joinToString("-")
        }

        fun fromSelectedBase(selectedPath: Path, selection: ExportSelection): ExportTargets {
            require(selection.hasOutput) { "Mindestens ein Ausgabeformat muss gewählt sein." }
            val absolute = selectedPath.toAbsolutePath().normalize()
            val fileName = absolute.fileName.toString()
            val baseName = KNOWN_SUFFIXES.firstOrNull { fileName.endsWith(it, ignoreCase = true) }
                ?.let { fileName.dropLast(it.length) }
                ?: fileName
            require(baseName.isNotBlank()) { "Der Ausgabename ist ungültig." }
            val base = absolute.resolveSibling(baseName)
            return ExportTargets(
                mapsforgeMap = base.resolveSibling("${base.fileName}.map").takeIf { selection.mapsforgeMap },
                mapsforgePoi = base.resolveSibling("${base.fileName}.poi").takeIf { selection.mapsforgePoi },
                filteredPbf = base.resolveSibling("${base.fileName}.osm.pbf").takeIf { selection.filteredPbf },
                elevationData = when (selection.elevationOutputFormat) {
                    de.arxsilex.maptools.converter.core.ElevationOutputFormat.SRTM_HGT ->
                        base.resolveSibling("${base.fileName}-hgt")
                    de.arxsilex.maptools.converter.core.ElevationOutputFormat.DTED ->
                        base.resolveSibling("${base.fileName}-dted")
                    else -> base.resolveSibling(
                        "${base.fileName}${selection.elevationOutputFormat.extension}",
                    )
                }.takeIf { selection.elevationData },
            )
        }

        private val KNOWN_SUFFIXES = listOf(
            ".osm.pbf",
            ".geotiff",
            ".pbf",
            ".map",
            ".poi",
            ".tiff",
            ".tif",
            ".asc",
            ".hgt",
            ".dt0",
            ".dt1",
            ".dt2",
        )
    }
}
