"""Tests for property exercises"""
import math
import unittest

from properties import Point, Person, Circle


class PointTests(unittest.TestCase):

    """Tests for Point."""

    def test_attributes(self):
        point = Point(1, 2, 3)
        self.assertEqual((point.x, point.y, point.z), (1, 2, 3))
        point.x = 4
        self.assertEqual(point.x, 4)

    def test_str(self):
        point = Point(1, 2, 3)
        self.assertEqual(str(point), "Point(1, 2, 3)")
        self.assertEqual(repr(point), "Point(1, 2, 3)")

    def test_magnitude(self):
        point = Point(2, 3, 6)
        self.assertEqual(point.magnitude, 7.0)
        point.y = 9
        self.assertEqual(point.magnitude, 11.0)

    @unittest.skip("Comment this line for Pythonic Points")
    def test_add(self):
        p1 = Point(1, 2, 3)
        p2 = Point(4, 5, 6)
        p3 = p1 + p2
        self.assertEqual(str(p3), "Point(5, 7, 9)")

    @unittest.skip("Comment this line for Pythonic Points")
    def test_multiply(self):
        p1 = Point(1, 2, 3)
        p2 = p1 * 2
        self.assertEqual(str(p2), "Point(2, 4, 6)")
        p3 = 2 * p1
        self.assertEqual(str(p3), "Point(2, 4, 6)")

    @unittest.skip("Comment this line for Pythonic Points")
    def test_equality(self):
        p1 = Point(1, 2, 3)
        p2 = Point(4, 5, 6)
        p3 = Point(1, 2, 3)
        self.assertEqual(p1, p3)
        self.assertNotEqual(p1, p2)
        self.assertTrue(p1 == p3)
        self.assertFalse(p1 != p3)
        self.assertFalse(p1 == p2)
        self.assertTrue(p1 != p2)
        self.assertFalse(p1 != p3)


class PersonTests(unittest.TestCase):

    """Tests for Person."""

    def test_construct(self):
        Person("Trey", "Hunner")

    def test_first_and_last_name_attributes(self):
        trey = Person("Trey", "Hunner")
        self.assertEqual(trey.first_name, "Trey")
        self.assertEqual(trey.last_name, "Hunner")

    def test_name_attribute(self):
        trey = Person("Trey", "Hunner")
        self.assertEqual(trey.name, "Trey Hunner")

    def test_change_names(self):
        trey = Person("Trey", "Hunner")
        trey.last_name = "Smith"
        self.assertEqual(trey.name, "Trey Smith")
        trey.first_name = "John"
        self.assertEqual(trey.name, "John Smith")


class CircleTests(unittest.TestCase):

    """Tests for Circle."""

    def test_radius(self):
        circle = Circle(5)
        self.assertEqual(circle.radius, 5)

    def test_default_radius(self):
        circle = Circle()
        self.assertEqual(circle.radius, 1)

    def test_diameter_changes(self):
        circle = Circle(2)
        self.assertEqual(circle.diameter, 4)
        circle.radius = 3
        self.assertEqual(circle.diameter, 6)

    def test_set_diameter(self):
        circle = Circle(2)
        self.assertEqual(circle.diameter, 4)
        circle.diameter = 3
        self.assertEqual(circle.radius, 1.5)

    def test_area(self):
        circle = Circle(2)
        self.assertEqual(circle.area, math.pi * 4)

    @unittest.skip("Comment this line to test Log Radius Changes")
    def test_radius_changes_logged(self):
        circle = Circle(2)
        self.assertEqual(circle.radius_changes, [2])
        circle.radius = 3
        self.assertEqual(circle.radius_changes, [2, 3])
        circle.diameter = 3
        self.assertEqual(circle.radius_changes, [2, 3, 1.5])

    @unittest.skip("Comment this line to test Set Radius Error")
    def test_no_negative_radius(self):
        circle = Circle(2)
        with self.assertRaises(ValueError) as context:
            circle.radius = -10
        self.assertEqual(str(context.exception), "Radius cannot be negative!")

    @unittest.skip("Comment this line to test Comparable Circle")
    def test_equality(self):
        circle_a = Circle(2)
        circle_b = Circle(2)
        circle_c = Circle(1)
        self.assertTrue(circle_a == circle_b)
        self.assertTrue(circle_b != circle_c != circle_a)
        self.assertFalse(circle_a != circle_b)
        self.assertFalse(circle_a == circle_c)
        self.assertFalse(circle_b == circle_c)
        circle_c.radius = 2
        self.assertTrue(circle_a == circle_b == circle_c)
        self.assertFalse(circle_b != circle_c)
        self.assertFalse(circle_a != circle_c)

    @unittest.skip("Comment this line to test Comparable Circle")
    def test_comparability(self):
        circle_a = Circle(1)
        circle_b = Circle(2)
        circle_c = Circle(3)
        self.assertTrue(circle_a < circle_b < circle_c)
        self.assertTrue(circle_a <= circle_b <= circle_c)
        self.assertFalse(circle_b < circle_a)
        self.assertFalse(circle_c < circle_b)
        self.assertTrue(circle_c > circle_b > circle_a)
        self.assertTrue(circle_c >= circle_b >= circle_a)
        self.assertFalse(circle_a > circle_b)
        self.assertFalse(circle_b > circle_c)


if __name__ == "__main__":
    from helpers import error_message

    error_message()
