import unittest
from shapely import geometry

class CoordsGetItemTestCase(unittest.TestCase):
    def test_index_2d_coords(self):
        c = [(float(x), float(-x)) for x in range(4)]
        g = geometry.LineString(c)
        for i in range(-4,4):
            self.assertTrue(g.coords[i] == c[i])
        self.assertRaises(IndexError, lambda: g.coords[4])
        self.assertRaises(IndexError, lambda: g.coords[-5])

    def test_index_3d_coords(self):
        c = [(float(x), float(-x), float(x*2)) for x in range(4)]
        g = geometry.LineString(c)
        for i in range(-4,4):
            self.assertTrue(g.coords[i] == c[i])
        self.assertRaises(IndexError, lambda: g.coords[4])
        self.assertRaises(IndexError, lambda: g.coords[-5])

    def test_index_coords_misc(self):
        g = geometry.LineString() # empty
        self.assertRaises(IndexError, lambda: g.coords[0])
        self.assertRaises(TypeError, lambda: g.coords[0.0])

    def test_slice_2d_coords(self):
        c = [(float(x), float(-x)) for x in range(4)]
        g = geometry.LineString(c)
        self.assertTrue(g.coords[1:] == c[1:])
        self.assertTrue(g.coords[:-1] == c[:-1])
        self.assertTrue(g.coords[::-1] == c[::-1])
        self.assertTrue(g.coords[::2] == c[::2])
        self.assertTrue(g.coords[:4] == c[:4])
        self.assertTrue(g.coords[4:] == c[4:] == [])

    def test_slice_3d_coords(self):
        c = [(float(x), float(-x), float(x*2)) for x in range(4)]
        g = geometry.LineString(c)
        self.assertTrue(g.coords[1:] == c[1:])
        self.assertTrue(g.coords[:-1] == c[:-1])
        self.assertTrue(g.coords[::-1] == c[::-1])
        self.assertTrue(g.coords[::2] == c[::2])
        self.assertTrue(g.coords[:4] == c[:4])
        self.assertTrue(g.coords[4:] == c[4:] == [])

class MultiGeomGetItemTestCase(unittest.TestCase):
    def test_index_multigeom(self):
        c = [(float(x), float(-x)) for x in range(4)]
        g = geometry.MultiPoint(c)
        for i in range(-4,4):
            self.assertTrue(g[i].equals(geometry.Point(c[i])))
        self.assertRaises(IndexError, lambda: g[4])
        self.assertRaises(IndexError, lambda: g[-5])

    def test_index_multigeom_misc(self):
        g = geometry.MultiLineString() # empty
        self.assertRaises(IndexError, lambda: g[0])
        self.assertRaises(TypeError, lambda: g[0.0])

    def test_slice_multigeom(self):
        c = [(float(x), float(-x)) for x in range(4)]
        g = geometry.MultiPoint(c)
        self.failUnlessEqual(type(g[:]), type(g))
        self.failUnlessEqual(len(g[:]), len(g))
        self.failUnless(g[1:].equals(geometry.MultiPoint(c[1:])))
        self.failUnless(g[:-1].equals(geometry.MultiPoint(c[:-1])))
        self.failUnless(g[::-1].equals(geometry.MultiPoint(c[::-1])))
        self.failUnless(g[4:].is_empty)

class LinearRingGetItemTestCase(unittest.TestCase):
    def test_index_linearring(self):
        shell = geometry.polygon.LinearRing([(0.0, 0.0), (70.0, 120.0),
                                             (140.0, 0.0), (0.0, 0.0)])
        holes = [geometry.polygon.LinearRing([(60.0, 80.0), (80.0, 80.0),
                                              (70.0, 60.0), (60.0, 80.0)]),
                 geometry.polygon.LinearRing([(30.0, 10.0), (50.0, 10.0),
                                              (40.0, 30.0), (30.0, 10.0)]),
                 geometry.polygon.LinearRing([(90.0, 10), (110.0, 10.0),
                                              (100.0, 30.0), (90.0, 10.0)])]
        g = geometry.Polygon(shell, holes)
        for i in range(-3,3):
            self.assertTrue(g.interiors[i].equals(holes[i]))
        self.assertRaises(IndexError, lambda: g.interiors[3])
        self.assertRaises(IndexError, lambda: g.interiors[-4])

    def test_index_linearring_misc(self):
        g = geometry.Polygon() # empty
        self.assertRaises(IndexError, lambda: g.interiors[0])
        self.assertRaises(TypeError, lambda: g.interiors[0.0])

    def test_slice_linearring(self):
        shell = geometry.polygon.LinearRing([(0.0, 0.0), (70.0, 120.0),
                                             (140.0, 0.0), (0.0, 0.0)])
        holes = [geometry.polygon.LinearRing([(60.0, 80.0), (80.0, 80.0),
                                              (70.0, 60.0), (60.0, 80.0)]),
                 geometry.polygon.LinearRing([(30.0, 10.0), (50.0, 10.0),
                                              (40.0, 30.0), (30.0, 10.0)]),
                 geometry.polygon.LinearRing([(90.0, 10), (110.0, 10.0),
                                              (100.0, 30.0), (90.0, 10.0)])]
        g = geometry.Polygon(shell, holes)
        self.assertTrue(all([a.equals(b) for (a, b) in zip(g.interiors[1:], holes[1:])]))
        self.assertTrue(all([a.equals(b) for (a, b) in zip(g.interiors[:-1], holes[:-1])]))
        self.assertTrue(all([a.equals(b) for (a, b) in zip(g.interiors[::-1], holes[::-1])]))
        self.assertTrue(all([a.equals(b) for (a, b) in zip(g.interiors[::2], holes[::2])]))
        self.assertTrue(all([a.equals(b) for (a, b) in zip(g.interiors[:3], holes[:3])]))
        self.assertTrue(g.interiors[3:] == holes[3:] == [])

def test_suite():
    loader = unittest.TestLoader()
    return unittest.TestSuite([
        unittest.TestLoader().loadTestsFromTestCase(CoordsGetItemTestCase),
        unittest.TestLoader().loadTestsFromTestCase(MultiGeomGetItemTestCase),
        unittest.TestLoader().loadTestsFromTestCase(LinearRingGetItemTestCase)])
