"""
Module for a Shape.
"""
from turtle import Turtle
from typing import List

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

    === Attributes ===
    @param corners list[Point]: Corners of this Shape
    @param perimeter float: length to traverse corners
    @param area float: area of this Shape
    """

    def __init__(self, corners: List['Point']) -> None:
        """ Create a new Shape self with corners.

        Assume that the corners are traversed in order, that the sides are equal
        length, and the vertices are right angles.

        @param self Shape: A subclass of shape
        @param corners list[Point]: A list of corners
        @rtype: None
        """
        self.corners = corners[:]
        self._turtle = Turtle()
        self._set_perimeter()
        self._set_area()

    def _set_perimeter(self)->None:
        """ Set Shape self's perimeter to the sum of the distances between
        corners.

        @param self Shape: This Shape
        @rtype: None
        """
        distances = []
        for i in range(len(self.corners)):
            distances.append(self.corners[i].distance(self.corners[i - 1]))
        self._perimeter = sum(distances)

    def _get_perimeter(self)->float:
        """ Get Shape self's perimeter

        @param self Shape: This Shape
        @rtype: float
        """
        return self._perimeter

    perimeter = property(_get_perimeter, None)

    def _set_area(self)->None:
        """ Set Shape self's are to be implemented in subclasses

        @param self Shape: This Shape
        @rtype: None
        """
        self._area= -1.0
        raise NotImplementedError("Subclass needs to implement")

    def _get_area(self)->float:
        """ Returns area.

        @param self Shape: This Shape
        @rtype: None
        """
        return self._area

    area = property(_get_area, None)

    def move_by(self, offset_point: 'Point')->None:
        """
        Move Shape self to a new position by adding Point offset_point to
        each corner.

        @param self Shape: This shape
        @param offset_point Point: point to move by
        @rtype: None
        """
        self.corners = [c + offset_point for c in self.corners]
        # equivalent to...
        # new_corners = []
        # for c in self.corners:
        #    new_corners.append(c + offset_point)
        # self.corners = new_corners

    def draw(self)->None:
        """
        Draw Shape self.

        @param self Shape: This shape
        @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)