import unittest
import random
import rectangle
import itertools as it
from point import Point
from point import RandomPointGenerator


class PointTest(unittest.TestCase):
    def test_init_with_no_arguement(self):
        point = Point()
        self.assertEqual(point.x, 0)
        self.assertEqual(point.y, 0)

    def test_init_with_no_arguement(self):
        point = Point(1)
        self.assertEqual(point.y, 0)
        
    def test_init_takes_at_most_two_arguments(self):
        with self.assertRaises(TypeError):
            point = Point(0, 0, 0)

    def test_eq(self):
        x = random.random()
        y = random.random()
        self.assertTrue(Point() == Point())
        self.assertTrue(Point(x) == Point(x))
        self.assertTrue(Point(x, y) == Point(x, y))

    def test_neq(self):
        x = random.random()
        y = random.random()
        self.assertFalse(Point(x) == Point(x + random.random()))
        self.assertFalse(Point(x, y) == Point(x + random.random(), y + random.random()))
        self.assertFalse(Point(x, y) == Point(x, y + random.random()))
        self.assertFalse(Point(x, y) == Point(x + random.random(), y))
                
    def test_retrieve_x_coordinate(self):
        x = random.random()
        point = Point(x, random.random())
        self.assertEqual(point.x, x)

    def test_x_coordinate_is_read_only(self):
        with self.assertRaises(AttributeError):
            point = Point(random.random(), random.random())
            point.x = 0

    def test_cannot_delete_x_coordinate(self):
        with self.assertRaises(AttributeError):
            point = Point(random.random(), random.random())
            del point.x
            
    def test_retrieve_y_coordinate(self):
        y = random.random()
        point = Point(random.random(), y)
        self.assertEqual(point.y, y)

    def test_y_coordinate_is_read_only(self):
        with self.assertRaises(AttributeError):
            point = Point(random.random(), random.random())
            point.y = 0

    def test_cannot_delete_y_coordinate(self):
        with self.assertRaises(AttributeError):
            point = Point(random.random(), random.random())
            del point.y

    def test_domination(self):
        point1 = Point(0, 0)
        point2 = Point(1, 1)
        self.assertTrue(point2.dominates(point1))
        self.assertFalse(point1.dominates(point2))
        self.assertFalse(point1.dominates(point1))                         
                         
    def test_stringify(self):
        point = Point()
        self.assertEquals(str(point), 'Point(%f,%f)' % (float(0), float(0)))
        x, y = random.random(), random.random()
        point = Point(x, y)
        self.assertEquals(str(point), 'Point(%f,%f)' % (x, y))


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


class RandomPointGeneratorTest(unittest.TestCase):
    def test_init_with_no_arguement(self):
        with self.assertRaises(TypeError):
            g = RandomPointGenerator()

    def test_point_in_rectangle(self):
        x_rand = random.random()
        y_rand = random.random()
        r = rectangle.Rectangle(Point(x_rand, y_rand), Point(x_rand + 1, y_rand + 1))
        for point in take(10, RandomPointGenerator(r)):
            self.assertTrue(point in r)


if __name__ == '__main__':
    point_suite = unittest.TestLoader().loadTestsFromTestCase(PointTest)
    random_point_generator_suite = unittest.TestLoader().loadTestsFromTestCase(RandomPointGeneratorTest)
    suite  = unittest.TestSuite([point_suite, random_point_generator_suite])
    unittest.TextTestRunner(verbosity = 2).run(suite)
