from turtle import Turtle
from point import Point


class Square:
    """
    A square shape that can draw itself, move, and
    report area and perimeter.

    === Attributes ===
    @type corners: list[Point]
       corners of this square
    @type perimeter: float
       length to traverse corners
    @type area: float
        area of this Square
    """
    def __init__(self, corners):
        """
        Create a new Square self with corners.

        @type self: Square
        @type corners: list[Point]
        @rtype: None
        """
        # shallow copy of corners
        self.corners = corners[:]
        self._turtle = Turtle()
        self._set_perimeter()
        self._set_area()

    def _set_perimeter(self):
        """
        Set Square self's perimeter to the sum of the distances
        between corners.

        @type self: Square
        @rtype: None
        """
        distance_list = []
        for i in range(len(self.corners)):
            distance_list.append(self.corners[i].distance(
                    self.corners[i - 1]))
        self._perimeter = sum(distance_list)

    def _get_perimeter(self):
        """
        Return the perimeter of this Square

        @type self: Square
        @rtype: float
        """
        return self._perimeter

    # perimeter is immutable --- no setter method in property
    perimeter = property(_get_perimeter)

    def _set_area(self):
        """
        Set the area of Square self to the square of
        its sides.

        @type self: Square
        @rtype: None
        """
        self._area = self.corners[0].distance(self.corners[1])**2

    def _get_area(self):
        """
        Return the area of Square self.

        @type self: Square
        @rtype: float

        >>> Square([Point(1, 1), Point(2, 1), Point(2, 2), Point(1, 2)]).area
        1.0
        """
        return self._area

    # area is immutable --- no setter method in property
    area = property(_get_area)

    def move_to(self, offset_point):
        """
        Move Square self to a new position by adding
        Point offset_point to each corner.

        @type self: Square
        @type offset_point: Point
        @rtype: None
        """
        # list comprehension
        # see course web page, week 2
        self.corners = [c.add(offset_point) for c in self.corners]
        # equivalent to...
        # new_corners = []
        #  for c in self.corners:
        #     new_corners.append(c.add(offset_point))

    def draw(self):
        """
        Draw Square self.

        @type self: Square
        @rtype: None
        """
        self._turtle.penup()
        self._turtle.goto(self.corners[-1].x, self.corners[-1].y)
        self._turtle.pendown()
        for i in range(len(self.corners)):
            self._turtle.goto(self.corners[i].x, self.corners[i].y)
        self._turtle.penup()
        self._turtle.goto(0, 0)


class RightAngleTriangle:
    """
    A right-angle triangle that can draw itself, move, and
    report area and perimeter.

    === Attributes ===
    @type corners: list[Point]
       corners of this square
    @type perimeter: float
       length to traverse corners
    """
    def __init__(self, corners):
        """
        Create a new RightAngleTriangle self with corners.

        corners[0] is the right angle.

        @type self: RightAngleTriangle
        @type corners: list[Point]
        @rtype: None
        """
        # shallow copy of corners
        self.corners = corners[:]
        self._turtle = Turtle()
        self._set_perimeter()
        self._set_area()

    def _set_perimeter(self):
        """
        Set Square self's perimeter to the sum of the distances
        between corners.

        @type self: Square
        @rtype: None
        """
        distance_list = []
        for i in range(len(self.corners)):
            distance_list.append(self.corners[i].distance(
                    self.corners[i - 1]))
        self._perimeter = sum(distance_list)

    def _get_perimeter(self):
        """
        Return the perimeter of this Square

        @type self: Square
        @rtype: float
        """
        return self._perimeter

    # perimeter is immutable --- no setter method
    perimeter = property(_get_perimeter)

    def _set_area(self):
        """
        Set the area of RightAngleTriangle self to the product of
        its legs, divided by 2.0

        @type self: RightAngleTriangle
        @rtype: None
        """
        leg1 = self.corners[-1].distance(self.corners[0])
        leg2 = self.corners[0].distance(self.corners[1])
        self._area = (leg1 * leg2) / 2.0

    def _get_area(self):
        """
        Return the area of RightAngleTriangle self.

        @type self: Square
        @rtype: float

        >>> RightAngleTriangle([Point(0, 0), Point(1, 0), Point(0, 2)]).area
        1.0
        """
        return self._area

    # area is immutable --- no setter method in property
    area = property(_get_area)

    def move_to(self, offset_point):
        """
        Move RightAngleTriangle self to a new position by adding
        Point offset_point to each corner.

        @type self: RightAngleTriangle
        @type offset_point: Point
        @rtype: None
        """
        # list comprehension
        # see course web page, week 2
        self.corners = [c.add(offset_point) for c in self.corners]
        # equivalent to...
        # new_corners = []
        #  for c in self.corners:
        #     new_corners.append(c.add(offset_point))

    def draw(self):
        """
        Draw RightAngleTriangle self.

        @type self: RightAngleTriangle
        @rtype: None
        """
        self._turtle.penup()
        self._turtle.goto(self.corners[-1].x, self.corners[-1].y)
        self._turtle.pendown()
        for i in range(len(self.corners)):
            self._turtle.goto(self.corners[i].x, self.corners[i].y)
        self._turtle.penup()
        self._turtle.goto(0, 0)


if __name__ == "__main__":
    import doctest
    doctest.testmod()
