################################################################################


import unittest
import random
from rectangle import Rectangle
from point import Point
from point import RandomPointGenerator
from quadtree import QuadTree
from quadtree import QuadTreeException
import itertools as it


################################################################################


def take(n, iterable):
    '''
    Return first n items of the iterable as a list
    '''
    return list(it.islice(iterable, n))


################################################################################


class QuadTreeTest(unittest.TestCase):

    def setUp(self):
        x = random.random()
        y = random.random()
        width = 100 * (random.random() + 1)
        height = 100 * (random.random() + 1)
        self.rectangle = Rectangle(Point(x, y), Point(x + width, y + height))
        self.granularity = 5

    def test_non_valid_granularity(self):
        with self.assertRaises(QuadTreeException):
            QuadTree([], 0)

    def test_empty_quadtree_has_zero_size(self):
        t = QuadTree([], random.randint(1, self.granularity))
        self.assertEquals(t.size(), 0)

    def test_empty_quaddtree_stores_no_point(self):
        t = QuadTree([], random.randint(1, self.granularity))
        self.assertEquals([p for p in t], [])

    def test_report_all_points_number_of_points(self):
        points = take(100, RandomPointGenerator(self.rectangle))
        t = QuadTree(points, self.granularity)
        self.assertEquals(len([p for p in t]), len(points))

    def test_report_all_points(self):
        points = take(1000, RandomPointGenerator(self.rectangle))
        t = QuadTree(points, self.granularity)
        for p in points:
            self.assertTrue(p in t)
        for p in t:
            self.assertTrue(p in points)


################################################################################

            
class QuadTreeQueryTest(unittest.TestCase):

    def setUp(self):
        x = random.random()
        y = random.random()
        width = 100 * (random.random() + 1)
        height = 100 * (random.random() + 1)
        self.rectangle = Rectangle(Point(x, y), Point(x + width, y + height))
        self.granularity = 5
        points = take(1000, RandomPointGenerator(self.rectangle))
        self.quadtree = QuadTree(points, self.granularity)

    def test_report_no_point_from_rectangle(self):
        query_rectangle = Rectangle(point.Point(self.rectangle.lower_left_point.x - 1,
                                                 self.rectangle.lower_left_point.x - 1),
                                    point.Point(self.rectangle.lower_left_point.x - (100 * (random.random() + 1)),
                                                 self.rectangle.lower_left_point.x - (100 * (random.random() + 1))))
        result = self.quadtree.report_points_in_rectangle(quary_rectangle)
        self.assertEquals(result, [])


################################################################################

            
if __name__ == '__main__':
    suite_quadtree = unittest.TestLoader().loadTestsFromTestCase(QuadTreeTest)
    suite_quadtree_query = unittest.TestLoader().loadTestsFromTestCase(QuadTreeTest)
    suite  = unittest.TestSuite([suite_quadtree, suite_quadtree_query])
    unittest.TextTestRunner(verbosity = 2).run(suite)


################################################################################
