import pygame
import random

# Define colors
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
BLACK = (0, 0, 0)

# Define window dimensions
WINDOW_WIDTH = 640
WINDOW_HEIGHT = 480

# Define block size and count
BLOCK_SIZE = 10
BLOCK_COUNT_X = WINDOW_WIDTH // BLOCK_SIZE
BLOCK_COUNT_Y = WINDOW_HEIGHT // BLOCK_SIZE

# Define water speed coefficients
WATER_SPEED = 7
WATER_GRAVITY = 2
WATER_VISCOSITY = 0.2

class Block:
    """
    Represents a block in the water simulation.
    """
    def __init__(self, x, y):
        """
        Initializes a block with given x and y coordinates.

        :param x: X coordinate of block.
        :type x: int
        :param y: Y coordinate of block.
        :type y: int
        """
        self.x = x
        self.y = y
        self.is_solid = False
        self.color = BLUE

    def set_solid(self, is_solid):
        """
        Sets the solidity of the block.

        :param is_solid: Whether or not the block is solid.
        :type is_solid: bool
        """
        self.is_solid = is_solid
        if is_solid:
            self.color = RED

    def set_color(self, color):
        """
        Sets the color of the block.

        :param color: Color to set the block to.
        :type color: tuple
        """
        self.color = color

class WaterSimulator:
    """
    Represents the water simulation.
    """
    def __init__(self):
        """
        Initializes the water simulator.
        """
        self.blocks = [[Block(x, y) for y in range(BLOCK_COUNT_Y)] for x in range(BLOCK_COUNT_X)]
        self.water = [[0 for y in range(BLOCK_COUNT_Y)] for x in range(BLOCK_COUNT_X)]
        self.colors = [[BLACK for y in range(BLOCK_COUNT_Y)] for x in range(BLOCK_COUNT_X)]

    def update(self):
        """
        Updates the water simulation.
        """
        # Update water speed
        for x in range(1, BLOCK_COUNT_X - 1):
            for y in range(1, BLOCK_COUNT_Y - 1):
                water_speed = self.water[x][y]
                if water_speed <= 0:
                    continue
                self.water[x][y] += WATER_GRAVITY
                self.water[x][y] -= WATER_VISCOSITY * (self.water[x][y] - self.water[x - 1][y])
                self.water[x][y] -= WATER_VISCOSITY * (self.water[x][y] - self.water[x + 1][y])
                self.water[x][y] -= WATER_VISCOSITY * (self.water[x][y] - self.water[x][y - 1])
                self.water[x][y] -= WATER_VISCOSITY * (self.water[x][y] - self.water[x][y + 1])
                if self.blocks[x][y].is_solid:
                    self.water[x][y] = 0
                if self.water[x][y] > BLOCK_SIZE and self.water[x][y] - BLOCK_SIZE >= self.water[x][y - 1]:
                    self.water[x][y] -= WATER_SPEED
                    self.water[x][y - 1] += WATER_SPEED

        # Update block colors based on water level
        for x in range(BLOCK_COUNT_X):
            for y in range(BLOCK_COUNT_Y):
                if self.water[x][y] > 0:
                    self.colors[x][y] = BLUE
                if self.water[x][y] > BLOCK_SIZE:
                    self.colors[x][y] = WHITE
                else:
                    self.colors[x][y] = self.blocks[x][y].color

    def add_water(self, x, y):
        """
        Adds water to a specified block.

        :param x: X coordinate of block.
        :type x: int
        :param y: Y coordinate of block.
        :type y: int
        """
        self.water[x][y] = BLOCK_SIZE

    def set_block(self, x, y, is_solid):
        """
        Sets the solidity of a specified block.

        :param x: X coordinate of block.
        :type x: int
        :param y: Y coordinate of block.
        :type y: int
        :param is_solid: Whether or not the block is solid.
        :type is_solid: bool
        """
        self.blocks[x][y].set_solid(is_solid)

    def set_color(self, x, y, color):
        """
        Sets the color of a specified block.

        :param x: X coordinate of block.
        :type x: int
        :param y: Y coordinate of block.
        :type y: int
        :param color: Color to set the block to.
        :type color: tuple
        """
        self.blocks[x][y].set_color(color)

    def draw(self, screen):
        """
        Draws the water simulation on the screen.

        :param screen: Pygame screen to draw on.
        :type screen: pygame.Surface
        """
        for x in range(BLOCK_COUNT_X):
            for y in range(BLOCK_COUNT_Y):
                pygame.draw.rect(screen, self.colors[x][y], (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))

# Initialize pygame
pygame.init()

# Create window
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('Water simulator')

# Create water simulator
simulator = WaterSimulator()

# Fill blocks randomly
for x in range(BLOCK_COUNT_X):
    for y in range(BLOCK_COUNT_Y):
        if random.randint(0, 10) == 0:
            simulator.set_block(x, y, True)

# Start game loop
running = True
while running:
    # Check events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONUP:
            # Add water and set block to solid
            x, y = event.pos
            x //= BLOCK_SIZE
            y //= BLOCK_SIZE
            simulator.add_water(x, y)
            simulator.set_block(x, y, True)
        if event.type == pygame.KEYUP:
            # Reset blocks
            if event.key == pygame.K_r:
                for x in range(BLOCK_COUNT_X):
                    for y in range(BLOCK_COUNT_Y):
                        simulator.set_block(x, y, False)
                        simulator.set_color(x, y, BLUE)
                simulator.water = [[0 for y in range(BLOCK_COUNT_Y)] for x in range(BLOCK_COUNT_X)]

    # Update simulation and draw on screen
    simulator.update()
    simulator.draw(screen)

    # Update screen
    pygame.display.flip()

# Quit pygame
pygame.quit() перепиши этот код, чтобы воду  и кирпичи надо было размещать