package cz.jzitnik.game.logic.services.falling;

import cz.jzitnik.game.Game;
import cz.jzitnik.game.annotations.BreaksFalling;
import cz.jzitnik.game.annotations.CustomLogic;
import cz.jzitnik.game.annotations.FallingBlock;
import cz.jzitnik.game.entities.Block;
import cz.jzitnik.game.logic.CustomLogicInterface;
import cz.jzitnik.tui.ScreenRenderer;

@CustomLogic
public class FallingLogic implements CustomLogicInterface {
    private static final int RADIUS = 30;

    @Override
    public void nextIteration(Game game, ScreenRenderer ignored) {
        var world = game.getWorld();
        int[] data = game.getPlayerCords();
        int playerX = data[0];
        int playerY = data[1];

        int startX = Math.max(0, playerX - RADIUS);
        int startY = Math.max(0, playerY - RADIUS);
        int endX = Math.min(world[0].length - 1, playerX + RADIUS);
        int endY = Math.min(world.length - 1, playerY + RADIUS);

        for (int y = startY; y <= endY; y++) {
            for (int x = startX; x <= endX; x++) {
                var blocks = world[y][x];

                if (world[y+1][x].stream().anyMatch(block -> block.getClass().isAnnotationPresent(BreaksFalling.class))) {
                    blocks.removeIf(block -> block.getClass().isAnnotationPresent(FallingBlock.class));
                }

                if (!world[y+1][x].stream().allMatch(block -> block.isGhost())) {
                    continue;
                }

                var fallingBlocks = blocks.stream().filter(block -> block.getClass().isAnnotationPresent(FallingBlock.class)).toList();
                for (Block block : fallingBlocks) {
                    blocks.remove(block);
                    world[y + 1][x].add(block);
                }
            }
        }
    }
}
