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

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

import java.util.*;

@CustomLogic
public class GrassGrowingLogic implements CustomLogicInterface {
    private static final int RADIUS = 35;

    @Override
    public void nextIteration(Game game, ScreenRenderer ignored) {
        int[] data = game.getPlayerCords();
        var world = game.getWorld();
        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 x = startX; x <= endX; x++) {
            for (int y = startY; y <= endY; y++) {
                List<Block> blocks = world[y][x];
                if (blocks.stream().anyMatch(block -> block.getBlockId().equals("dirt"))) {
                    // Dirt
                    if (world[y - 1][x].stream()
                            .allMatch(block -> block.isGhost() || block.isMob() || block.getBlockId().equals("air"))
                            && isGrassBesides(world, x, y)) {
                        var dirt = blocks.stream().filter(i -> i.getBlockId().equals("dirt")).findFirst().get();
                        var dirtData = (GrassDirtData) dirt.getData();
                        if (dirtData.getAge() == 9) {
                            world[y][x].remove(dirt);
                            world[y][x].add(ItemBlockSupplier.getBlock("grass"));
                        } else {
                            dirtData.increaseAge();
                        }

                    }
                } else if (blocks.stream().anyMatch(block -> block.getBlockId().equals("grass"))) {
                    // Grass
                    if (!world[y - 1][x].stream()
                            .allMatch(block -> block.isGhost() || block.isMob() || block.getBlockId().equals("air"))) {
                        var grass = blocks.stream().filter(i -> i.getBlockId().equals("grass")).findFirst().get();
                        var grassData = (GrassDirtData) grass.getData();
                        if (grassData.getAge() == 9) {
                            world[y][x].remove(grass);
                            world[y][x].add(ItemBlockSupplier.getBlock("dirt"));
                        } else {
                            grassData.increaseAge();
                        }
                    }
                }
            }
        }

    }

    private boolean isGrass(List<Block>[][] world, int x, int y) {
        return world[y][x].stream().anyMatch(i -> i.getBlockId().equals("grass"));
    }

    private boolean isGrassBesides(List<Block>[][] world, int x, int y) {
        if (isGrass(world, x + 1, y)) {
            return true;
        }

        if (isGrass(world, x + 1, y + 1)) {
            return true;
        }

        if (isGrass(world, x + 1, y - 1)) {
            return true;
        }

        if (isGrass(world, x - 1, y)) {
            return true;
        }

        if (isGrass(world, x - 1, y + 1)) {
            return true;
        }

        if (isGrass(world, x - 1, y - 1)) {
            return true;
        }

        return false;
    }
}
