"""
    https://stepik.org/lesson/468997/step/10?unit=459818
    Реализуйте с помощью библиотеки Graph рисунки "Домик" и "Лягушка"

    Библиотека graph: https://kpolyakov.spb.ru/download/pygraph.zip
"""

from typing import NamedTuple
from graph import penColor, brushColor, rectangle, polygon, penSize, label, circle, run

black = "black"


class Point(NamedTuple):
    x: int | float
    y: int | float

    def __add__(self, other):
        if isinstance(other, self.__class__):
            return self.__class__(self.x + other.x, self.y + other.y)
        if isinstance(other, (int, float)):
            return self.__class__(self.x + other, self.y + other)
        return NotImplemented


class Colors(NamedTuple):
    pen: str | tuple[int, int, int]
    brush: str | tuple[int, int, int]


class Figure:
    def __init__(
        self,
        point=Point(0, 0),
        size=Point(1, 1),
        colors=Colors(black, "white"),
        pen_size=1,
    ):
        self.point, self.size, self.colors, self.pen_size = (
            point,
            size,
            colors,
            pen_size,
        )

    def draw(self):
        penColor(self.colors.pen)
        brushColor(self.colors.brush)
        penSize(self.pen_size)


class Box(Figure):
    def draw(self):
        super().draw()
        rectangle(*self.point, *(self.point + self.size))


class TriangleA(Figure):
    def get_mid(self):
        return self.point + Point(self.size.x / 2, -self.size.y)

    def draw(self):
        super().draw()
        end = self.point + Point(self.size.x, 0)
        polygon([self.point, self.get_mid(), end, self.point])


class TriangleV(TriangleA):
    def get_mid(self):
        return self.point + Point(self.size.x / 2, self.size.y)


class Circle(Figure):
    def draw(self):
        super().draw()
        circle(*self.point, self.size.x)


class Composite(Figure):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.childs = []

    def add(self, fig):
        fig.point = self.point + fig.point
        self.childs.append(fig)

    def draw(self):
        super().draw()
        for fig in self.childs:
            fig.draw()


def home(x, y):
    fig = Composite(Point(x, y))
    fig.add(Box(size=Point(100, 100), colors=Colors(black, "green3")))
    fig.add(TriangleA(Point(-20, 0), Point(140, 50), Colors(black, "blue")))
    fig.add(
        Box(
            Point(30, 20),
            Point(40, 50),
            Colors("white", black),
            5,
        )
    )
    fig.draw()


def frog(x, y):
    fig = Composite(Point(x, y))
    fig.add(Circle(size=Point(35, 35), colors=Colors(black, "red")))
    fig.add(TriangleA(Point(35, 0), Point(180, 60), Colors(black, "indigo")))
    fig.add(TriangleV(Point(35, -60), Point(180, 60), Colors(black, "green1")))
    fig.add(Circle(Point(250, 0), Point(35, 35), Colors(black, "yellow")))
    fig.draw()


def main():
    font = ("Arial", 18)
    indigo = "indigo"

    label("«3»", 10, 20, font=font, foreground=indigo)
    label(": «Домик»", 51, 20, font=font)
    home(200, 100)

    label("«4»", 10, 280, font=font, foreground=indigo)
    label(": «Лягушка»", 51, 280, font=font)
    frog(120, 400)

    run()


if __name__ == "__main__":
    main()