package de.arxsilex.maptools.converter.worker

import de.arxsilex.maptools.converter.core.MapsforgeProcessorType
import java.nio.file.Files
import java.io.RandomAccessFile
import kotlin.io.path.createTempFile
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class MapsforgeRequestTest {
    @Test
    fun `builds map and poi writer pipelines with correct bbox order`() {
        val input = createTempFile(suffix = ".osm.pbf")
        try {
            val request = MapsforgeRequest.parse(
                arrayOf(
                    "mapsforge", "--input", input.toString(),
                    "--map-output", input.resolveSibling("sample.map").toString(),
                    "--poi-output", input.resolveSibling("sample.poi").toString(),
                    "--map-format", "5",
                    "--poi-schema", "4",
                    "--temp-dir", input.resolveSibling("session-temp").toString(),
                    "--west", "8", "--south", "50", "--east", "9", "--north", "51",
                    "--roads", "true", "--paths", "true", "--buildings", "true",
                    "--land-water", "true", "--pois", "true", "--metadata", "true",
                ),
            )
            assertTrue(
                "bbox=50.0,8.0,51.0,9.0" in request.mapArguments(
                    input.resolveSibling("a.map"),
                    input.resolveSibling("mapping.xml"),
                ),
            )
            assertEquals(input.resolveSibling("session-temp"), request.temporaryDirectory)
            assertEquals(MapsforgeProcessorType.RAM, request.processorType)
            assertTrue("type=ram" in request.mapArguments(
                input.resolveSibling("a.map"),
                input.resolveSibling("mapping.xml"),
            ))
            assertTrue(request.poiArguments(input.resolveSibling("a.poi")).contains("--poi-writer"))
            assertTrue(
                "threads=${request.mapWriterThreads()}" in request.mapArguments(
                    input.resolveSibling("a.map"),
                    input.resolveSibling("mapping.xml"),
                ),
            )
            assertTrue("tag-values=true" in request.mapArguments(
                input.resolveSibling("a.map"),
                input.resolveSibling("mapping.xml"),
            ))
            assertEquals(8, request.mapWriterThreads(32))
            assertEquals(1, request.mapWriterThreads(1))
        } finally {
            Files.deleteIfExists(input)
        }
    }

    @Test
    fun `uses ram for medium selections and hd only above the bounded heap threshold`() {
        val input = createTempFile(suffix = ".osm.pbf")
        try {
            val request = MapsforgeRequest.parse(
                arrayOf(
                    "mapsforge", "--input", input.toString(),
                    "--map-output", input.resolveSibling("sample.map").toString(),
                    "--poi-output", "-", "--map-format", "5", "--poi-schema", "4",
                    "--temp-dir", input.resolveSibling("session-temp").toString(),
                    "--west", "8", "--south", "50", "--east", "9", "--north", "51",
                    "--roads", "true", "--paths", "true", "--buildings", "true",
                    "--land-water", "true", "--pois", "true", "--metadata", "true",
                ),
            )

            RandomAccessFile(input.toFile(), "rw").use { it.setLength(231_776_986L) }
            assertEquals(MapsforgeProcessorType.RAM, request.processorType)

            RandomAccessFile(input.toFile(), "rw").use { it.setLength(257L * 1024L * 1024L) }
            val largeRequest = MapsforgeRequest.parse(
                arrayOf(
                    "mapsforge", "--input", input.toString(),
                    "--map-output", input.resolveSibling("large.map").toString(),
                    "--poi-output", "-", "--map-format", "5", "--poi-schema", "4",
                    "--temp-dir", input.resolveSibling("session-temp").toString(),
                    "--west", "8", "--south", "50", "--east", "9", "--north", "51",
                    "--roads", "true", "--paths", "true", "--buildings", "true",
                    "--land-water", "true", "--pois", "true", "--metadata", "true",
                ),
            )
            assertEquals(MapsforgeProcessorType.HD, largeRequest.processorType)
        } finally {
            Files.deleteIfExists(input)
        }
    }

    @Test
    fun `explicit processor overrides the compressed input size heuristic`() {
        val input = createTempFile(suffix = ".osm.pbf")
        try {
            val request = MapsforgeRequest.parse(
                arrayOf(
                    "mapsforge", "--input", input.toString(),
                    "--map-output", input.resolveSibling("sample.map").toString(),
                    "--poi-output", "-", "--map-format", "5", "--poi-schema", "4",
                    "--processor", "hd", "--temp-dir", input.resolveSibling("session-temp").toString(),
                    "--west", "8", "--south", "50", "--east", "9", "--north", "51",
                    "--roads", "true", "--paths", "true", "--buildings", "true",
                    "--land-water", "true", "--pois", "true", "--metadata", "true",
                ),
            )

            assertEquals(MapsforgeProcessorType.HD, request.processorType)
        } finally {
            Files.deleteIfExists(input)
        }
    }

    @Test
    fun `disables variable tag values for map format version four`() {
        val input = createTempFile(suffix = ".osm.pbf")
        try {
            val request = MapsforgeRequest.parse(
                arrayOf(
                    "mapsforge", "--input", input.toString(),
                    "--map-output", input.resolveSibling("legacy.map").toString(),
                    "--poi-output", "-", "--map-format", "4", "--poi-schema", "3",
                    "--temp-dir", input.resolveSibling("session-temp").toString(),
                    "--west", "8", "--south", "50", "--east", "9", "--north", "51",
                    "--roads", "true", "--paths", "true", "--buildings", "true",
                    "--land-water", "true", "--pois", "true", "--metadata", "true",
                ),
            )

            assertTrue("tag-values=false" in request.mapArguments(
                input.resolveSibling("legacy.map"),
                input.resolveSibling("mapping.xml"),
            ))
            assertTrue("preferred-languages=de,en" in request.mapArguments(
                input.resolveSibling("legacy.map"),
                input.resolveSibling("mapping.xml"),
            ))
        } finally {
            Files.deleteIfExists(input)
        }
    }
}
