package be.kdg.labyrinth.JavaFX.model;

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

public class PlayerModel {
    private int playerRow;
    private int playerCol;
    private final List<int[]> trail;
    private final LabyrinthModel labyrinthModel;

    public PlayerModel(int startRow, int startCol, LabyrinthModel labyrinthModel) {
        this.playerRow = startRow;
        this.playerCol = startCol;
        this.trail = new ArrayList<>();
        this.trail.add(new int[]{playerRow, playerCol});
        this.labyrinthModel = labyrinthModel;
    }

    public int getPlayerRow() {
        return playerRow;
    }

    public int getPlayerCol() {
        return playerCol;
    }

    public List<int[]> getTrail() {
        return trail;
    }

    public void movePlayer(int deltaRow, int deltaCol, char[][] labyrinth) {
        int newRow = playerRow + deltaRow; //hier wordt de nieuwe positite van de speler berekent. Als bijvoorbeeld deltarow -1 is en deltacol 0 is dan beweeg je omhoog
        int newCol = playerCol + deltaCol;

        if (newRow >= 0 && newRow < labyrinth.length && newCol >= 0 && newCol < labyrinth[0].length) { //controleert of de rijindex niet negatief is en binnen het aantal rijen valt van het labyrinth. Dit is ook hetzelfde met de kolom alleen staat er een [0] omdat we maar 1 rij afgaan om te weten hoeveel kolommen er zijn.
            if (labyrinth[newRow][newCol] == '#') { //als je een muur aanraakt wordt je gereset.
                reset(labyrinthModel.findStartRow(), labyrinthModel.findStartCol(labyrinthModel.findStartRow())); //hier wordt gebruik gemaakt van de reset methode om de gebruiker te teleporteren naar zijn beginpositie
            } else if (labyrinth[newRow][newCol] == '.' || labyrinth[newRow][newCol] == 'E' || labyrinth[newRow][newCol] == 'O') { //als de speler op een nieuwe pad staat of uitgang of teleportatiepunt
                playerRow = newRow; //wordt de nieuwe rij berekent en kolom
                playerCol = newCol;
                trail.add(new int[]{playerRow, playerCol});

                if (labyrinth[playerRow][playerCol] == 'O') { //als je op een teleportatiepunt staat dan wordt je geteleporteert door de teleportPlayer Methode
                    teleportPlayer(labyrinth);
                }
            }
        } else { //als de speler buiten de grenzen is van het labyrinth wordt de speler ook gereset naar de startpositie.
            reset(labyrinthModel.findStartRow(), labyrinthModel.findStartCol(labyrinthModel.findStartRow()));
        }
    }

    private void teleportPlayer(char[][] labyrinth) {
        Random rand = new Random();
        int newRow, newCol;
        int maxAttempts = 100; // Maximum aantal pogingen
        int attempts = 0;

        do {
            newRow = rand.nextInt(labyrinth.length); //hier lezen we het volledige labyrinth om te weten te komen hoeveel rijen er zijn.
            newCol = rand.nextInt(labyrinth[0].length); //gaat de eerste rij [0] alleen lezen om te weten te komen hoeveel kolommen er zijn
            attempts++;
        } while (labyrinth[newRow][newCol] != '.' && attempts < maxAttempts); //gaat dit blijven uitvoeren totdat er een doorgang is.

        if (attempts >= maxAttempts) { //als de attempts groter of gelijk zijn aan de maxattempts dat wordt je geteleporteerd naar de startpositie
            newRow = labyrinthModel.findStartRow();
            newCol = labyrinthModel.findStartCol(newRow);
        }

        playerRow = newRow;
        playerCol = newCol;
        trail.add(new int[]{playerRow, playerCol});
    }

    public void reset(int startRow, int startCol) { //reset positie van de speler.
        this.playerRow = startRow;
        this.playerCol = startCol;
        this.trail.clear();
        this.trail.add(new int[]{playerRow, playerCol});
    }
}