from django.contrib.gis.geos import (
    GeometryCollection,
    GEOSGeometry,
    LineString,
    MultiLineString,
    MultiPolygon,
    Point,
    Polygon,
)
from django.test import TestCase

from teramap.utils import attr_or_key, geom_accuracy, round_geom


class UtilsTest(TestCase):
    def test_attr_or_key(self):
        class Obj(object):
            foo = "bar"

        o = Obj()
        d = dict(bar="foo")

        self.assertEqual(attr_or_key(o, "foo"), "bar")
        self.assertEqual(attr_or_key(d, "bar"), "foo")

    def test_round_geom(self):
        self.assertEqual(round_geom([1, 2], 6), [1, 2])
        self.assertEqual(round_geom([[1, 3], [3, 4]], 6), [[1, 3], [3, 4]])

        self.assertEqual(round_geom([1.1122, 1.2233], 2), [1.11, 1.22])
        self.assertEqual(round_geom([[1, 2], [1.1122, 1.2233]], 2), [[1, 2], [1.11, 1.22]])

    def test_geom_accuracy(self):
        square = lambda x: ((0, 0), (0, x), (x, x), (x, 0), (0, 0))
        testcases = (
            (Point(0, 2), 10),
            (LineString(square(0.5)), 40729),
            (MultiLineString(LineString(square(1)), LineString(square(1))), 81458),
            (Polygon(square(1)), 81458),
            (Polygon(square(0.001)), 81),
            (MultiPolygon(Polygon(square(1)), Polygon(square(1))), 81458),
            (GEOSGeometry("POINT(0 2)"), 10),
            (GEOSGeometry("MULTILINESTRING ((1 1, 2 2, 1 4), (4 4, 3 3, 4 2, 3 1))"), 253564),
            (GEOSGeometry("MULTIPOLYGON (((3 2, 4.5 4, 1 4, 3 2)), ((1.5 .5, 4 1, 1 2, .5 1, 1.5 .5)))"), 301190),
        )
        for geom, expected in testcases:
            with self.subTest(geom_type=type(geom).__name__):
                self.assertEqual(geom_accuracy(geom), expected)

        with self.subTest("GeometryCollection raises error"), self.assertRaises(ValueError):
            geom_accuracy(GeometryCollection([]))
