from __future__ import annotations

from copy import deepcopy
from random import randint
from typing import *  # type: ignore

from rio import Component, event, Column, Row, Color, Rectangle



class ConwayPage(Component):
    """
    This is an Easter egg.
    """

    active_generation: list[list] = []
    rows: int = 36
    cols: int = 20

    @event.periodic(1)
    async def calc_next_gen(self) -> None:
        self.create_next_grid()

    @event.on_populate
    def prepare(self) -> None:
        self.active_generation = self.create_initial_grid()

    def create_initial_grid(self) -> list[list]:
        grid = []
        for row in range(self.rows):
            grid_rows = []
            for col in range(self.cols):
                if randint(0, 7) == 0:
                    grid_rows += [1]
                else:
                    grid_rows += [0]
            grid += [grid_rows]
        return grid

    def create_next_grid(self) -> None:
        next_grid = deepcopy(self.active_generation)

        for row in range(self.rows):
            for col in range(self.cols):
                live_neighbors = self.get_live_neighbors(row, col, self.active_generation)

                if live_neighbors < 2 or live_neighbors > 3:
                    next_grid[row][col] = 0
                elif live_neighbors == 3 and self.active_generation[row][col] == 0:
                    next_grid[row][col] = 1
                else:
                    next_grid[row][col] = self.active_generation[row][col]

        self.active_generation = next_grid

    def get_live_neighbors(self, row: int, col: int, grid: list[list]) -> int:
        life_sum = 0
        for i in range(-1, 2):
            for j in range(-1, 2):
                if not (i == 0 and j == 0):
                    life_sum += grid[((row + i) % self.rows)][((col + j) % self.cols)]
        return life_sum

    def grid_changing(self, next_grid: list[list]) -> bool:
        for row in range(self.rows):
            for col in range(self.cols):
                if not self.active_generation[row][col] == next_grid[row][col]:
                    return True
        return False

    def build(self) -> Component:
        rows = []

        for row in self.active_generation:
            rectangles = []

            for cell in row:
                color = Color.WHITE if cell == 1 else Color.BLACK
                rectangles.append(Rectangle(fill=color, transition_time=0.3))

            rows.append(Row(*rectangles))

        return Column(*rows)
