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

import java.util.List;
import java.util.Random;

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

@CustomLogic
public class FireSpreadingLogic implements CustomLogicInterface {
    private static final int RADIUS = 30;
    private Random random = new Random();

    @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];

                for (Block block : blocks) {
                    if ((block.isOnFire() && !block.isMob()) && block.getClass().getAnnotation(Flamable.class).value()) {
                        int maxTime = random.nextInt(30) + 15;
                        block.setBurningTime2(block.getBurningTime2() + 1);
                        if (block.getBurningTime2() >= maxTime) {
                            world[y][x].remove(block);
                        } else {
                            spreadFireToNeighbors(world, x, y);
                        }
                    }
                }
            }
        }
    }

    private void spreadFireToNeighbors(List<Block>[][] world, int x, int y) {
        checkAndSpreadFire(world, x + 1, y);
        checkAndSpreadFire(world, x - 1, y);
        checkAndSpreadFire(world, x, y + 1);
        checkAndSpreadFire(world, x, y - 1);
    }

    private void checkAndSpreadFire(List<Block>[][] world, int x, int y) {
        if (x < 0 || y < 0 || x >= world[0].length || y >= world.length) {
            return;
        }

        var blocks = world[y][x];

        for (Block block : blocks) {
            if (block.getClass().isAnnotationPresent(Flamable.class) && !block.isOnFire()) {
                int maxTime = random.nextInt(8) + 5;
                block.setBurningTime(block.getBurningTime() + 1);
                if (block.getBurningTime() >= maxTime) {
                    block.setOnFire(true);
                    block.setBurningTime(0);
                }
            }
        }
    }
}
