package de.arxsilex.maptools.converter.core

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue

class GeoBoundsTest {
    @Test
    fun `converts normalized selection to geographic coordinates`() {
        val bounds = GeoBounds(west = 10.0, south = 40.0, east = 20.0, north = 50.0)

        val subset = bounds.subset(NormalizedMapArea(0.25f, 0.2f, 0.75f, 0.8f))

        assertEquals(12.5, subset.west)
        assertEquals(42.0, subset.south, 0.000001)
        assertEquals(17.5, subset.east)
        assertEquals(48.0, subset.north, 0.000001)
    }

    @Test
    fun `converts edited geographic coordinates back to normalized selection`() {
        val bounds = GeoBounds(west = 10.0, south = 40.0, east = 20.0, north = 50.0)
        val geographicSelection = GeoBounds(west = 12.5, south = 42.0, east = 17.5, north = 48.0)

        val normalized = bounds.normalizedAreaFor(geographicSelection)

        assertEquals(NormalizedMapArea(0.25f, 0.2f, 0.75f, 0.8f), normalized)
        val roundTrip = bounds.subset(normalized)
        assertEquals(geographicSelection.west, roundTrip.west, 0.000001)
        assertEquals(geographicSelection.south, roundTrip.south, 0.000001)
        assertEquals(geographicSelection.east, roundTrip.east, 0.000001)
        assertEquals(geographicSelection.north, roundTrip.north, 0.000001)
    }

    @Test
    fun `rejects edited selection outside source bounds`() {
        val bounds = GeoBounds(west = 10.0, south = 40.0, east = 20.0, north = 50.0)

        assertFailsWith<IllegalArgumentException> {
            bounds.normalizedAreaFor(GeoBounds(west = 9.0, south = 42.0, east = 17.5, north = 48.0))
        }
    }

    @Test
    fun `rejects inverted bounds`() {
        assertFailsWith<IllegalArgumentException> {
            GeoBounds(west = 20.0, south = 40.0, east = 10.0, north = 50.0)
        }
    }

    @Test
    fun `combines and intersects source bounds`() {
        val hessen = GeoBounds(7.7, 49.3, 10.3, 51.7)
        val nrw = GeoBounds(5.8, 50.3, 9.5, 52.6)
        val bavaria = GeoBounds(8.9, 47.2, 13.9, 50.6)

        assertEquals(GeoBounds(5.8, 49.3, 10.3, 52.6), hessen.union(nrw))
        assertTrue(hessen.intersects(nrw))
        assertTrue(hessen.intersects(bavaria))
        assertFalse(nrw.intersects(GeoBounds(12.0, 47.0, 13.0, 48.0)))
        assertEquals(GeoBounds(5.8, 47.2, 13.9, 52.6), listOf(hessen, nrw, bavaria).unionOrNull())
    }
}
