package eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense;

import eu.mhsl.minenet.minigames.instance.Dimension;
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
import eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense.generator.MazeGenerator;
import eu.mhsl.minenet.minigames.score.LastWinsScore;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.batch.AbsoluteBlockBatch;
import net.minestom.server.instance.block.Block;

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

public class Towerdefense extends StatelessGame {
    private final Random random = new Random();
    private final AbsoluteBlockBatch mazeBatch = new AbsoluteBlockBatch();
    private final List<Pos> mazePath = new ArrayList<>();
    private List<TowerdefenseRoom> instances = new ArrayList<>();

    public Towerdefense() {
        super(Dimension.NETHER.key, "Towerdefense", new LastWinsScore());

        setGenerator(new MazeGenerator());
        this.generateMaze();
    }

    private void generateMaze() {
        Pos position = new Pos(0, 0, 0);
        this.addMazePosition(position, Block.GREEN_WOOL);

        List<Integer> previousDirections = new ArrayList<>();
        int direction = 1;      // 0 -> right; 1 -> straight; 2 -> left
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 3; j++) {
                position = position.add(direction-1,0,direction%2);
                this.addMazePosition(position, Block.WHITE_WOOL);
            }

            int origin = 0;
            int bound = 3;
            long rightLeftDifference = previousDirections.stream().filter(integer -> integer == 0).count() - previousDirections.stream().filter(integer -> integer == 2).count();
            if(rightLeftDifference >= 2 || direction == 2) origin = 1;
            if(rightLeftDifference <= -2 || direction == 0) bound = 2;
            direction = this.random.nextInt(origin, bound);
            previousDirections.add(direction);
        }
        this.addMazePosition(position, Block.WHITE_WOOL);
        this.addMazePosition(position.add(0,0,1), Block.WHITE_WOOL);
        this.addMazePosition(position.add(0,0,2), Block.RED_WOOL);
    }

    private void addMazePosition(Pos position, Block pathBlock) {
        this.mazeBatch.setBlock(position, pathBlock);
        this.mazePath.add(position.add(0.5,1,0.5));
    }

    public AbsoluteBlockBatch getMazeBatch() {
        return this.mazeBatch;
    }

    public List<Pos> getMazePath() {
        return this.mazePath;
    }

    @Override
    protected boolean onPlayerJoin(Player p) {
        TowerdefenseRoom newRoom = new TowerdefenseRoom(p, this);
        this.instances.add(newRoom);
        p.setInstance(newRoom);
        newRoom.startWave(List.of(EntityType.ENDERMAN, EntityType.BLAZE, EntityType.PLAYER, EntityType.HORSE, EntityType.ARMOR_STAND, EntityType.SKELETON));
        return false;
    }
}
