package de.arxsilex.maptools.converter.desktop

import de.arxsilex.maptools.converter.core.GeoBounds
import de.arxsilex.maptools.converter.core.preview.PreviewDataset
import de.arxsilex.maptools.converter.core.preview.PreviewLabel
import de.arxsilex.maptools.converter.core.preview.PreviewLabelClass
import de.arxsilex.maptools.converter.core.InputFileInfo
import de.arxsilex.maptools.converter.core.InputFormat
import java.nio.file.Files
import java.sql.DriverManager
import kotlin.test.Test
import kotlin.test.assertEquals

class PreviewSearchTest {
    @Test
    fun `finds names case and accent independently and prioritizes prefix matches`() {
        val dataset = PreviewDataset(
            GeoBounds(7.0, 49.0, 9.0, 51.0), emptyList(), emptyList(), 0, 0,
            labels = listOf(
                PreviewLabel(50.0, 8.0, "Café Mitte", PreviewLabelClass.POI, 30),
                PreviewLabel(50.1, 8.1, "Mittelweg", PreviewLabelClass.ROAD, 28),
            ),
        )

        assertEquals(listOf("Mittelweg", "Café Mitte"), PreviewSearch.find(dataset, "mit").map { it.text })
        assertEquals(listOf("Café Mitte"), PreviewSearch.find(dataset, "cafe").map { it.text })
    }

    @Test
    fun `searches the complete mapsforge poi cache and returns its position`() {
        val database = Files.createTempFile("preview-search", ".poi")
        try {
            Class.forName("org.sqlite.JDBC")
            DriverManager.getConnection("jdbc:sqlite:${database.toAbsolutePath()}").use { connection ->
                connection.createStatement().use { statement ->
                    statement.execute("CREATE TABLE poi_data (id INTEGER PRIMARY KEY, data TEXT)")
                    statement.execute("CREATE TABLE poi_index (id INTEGER PRIMARY KEY, minLat REAL, maxLat REAL, minLon REAL, maxLon REAL)")
                    statement.execute("CREATE VIRTUAL TABLE poi_data_fts USING fts5(data, content='poi_data', content_rowid='id')")
                    statement.execute("INSERT INTO poi_data VALUES (7, 'amenity=cafe\nname=Café Waldblick')")
                    statement.execute("INSERT INTO poi_index VALUES (7, 50.0, 50.2, 8.0, 8.2)")
                    statement.execute("INSERT INTO poi_data_fts(poi_data_fts) VALUES ('rebuild')")
                }
            }
            val source = PreviewDetailSource(
                InputFileInfo("fixture.pbf", "fixture.pbf", 1, InputFormat.OSM_PBF),
                mapPath = database.resolveSibling("fixture.map"),
                poiPath = database,
            )

            val result = PreviewSearch.findPoiDatabases(listOf(source), "Cafe Wald")

            assertEquals(listOf("Café Waldblick"), result.map { it.text })
            assertEquals(50.1, result.single().latitude)
            assertEquals(8.1, result.single().longitude)
        } finally {
            Files.deleteIfExists(database)
        }
    }

    @Test
    fun `searches poi version three without fts accent independently`() {
        val database = Files.createTempFile("preview-search-v3", ".poi")
        try {
            Class.forName("org.sqlite.JDBC")
            DriverManager.getConnection("jdbc:sqlite:${database.toAbsolutePath()}").use { connection ->
                connection.createStatement().use { statement ->
                    statement.execute("CREATE TABLE poi_data (id INTEGER PRIMARY KEY, data TEXT)")
                    statement.execute("CREATE TABLE poi_index (id INTEGER PRIMARY KEY, lat REAL, lon REAL)")
                    statement.execute("INSERT INTO poi_data VALUES (8, 'tourism=viewpoint\nname=Café Fernsicht')")
                    statement.execute("INSERT INTO poi_index VALUES (8, 50.4, 8.4)")
                }
            }
            val source = PreviewDetailSource(
                InputFileInfo("fixture.poi", "fixture.poi", 1, InputFormat.MAPSFORGE_POI),
                mapPath = null,
                poiPath = database,
            )

            val result = PreviewSearch.findPoiDatabases(listOf(source), "Cafe Fern")

            assertEquals(listOf("Café Fernsicht"), result.map { it.text })
            assertEquals(50.4, result.single().latitude)
        } finally {
            Files.deleteIfExists(database)
        }
    }
}
