package be.kdg.labyrinth.JavaFX.view;

import javafx.geometry.Pos;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class GameView extends BorderPane {
    private final Canvas canvas;
    private final GraphicsContext gc;
    private Label titleLabel;
    private Label timeLabel;
    private Label playerPositionLabel;
    private Label scoresLabel;
    private Label keyPressedLabel;
    private Button backButton; // Nieuwe knop om terug te gaan naar het startscherm
    private MenuBar menuBar;
    private MenuItem aboutMenuItem;
    private MenuItem tutorialMenuItem;
    private int tileSize;
    private final int rows;
    private final int cols;
    private final String playerName;
    private final String difficulty;

    // Afbeeldingen voor de tiles
    private final Image bushImage;
    private final Image pathImage;
    private final Image startImage;
    private final Image caveImage;
    private final Image flagImage;
    private final Image playerImage;

    public GameView(double width, double height, int rows, int cols, String playerName, String difficulty) {
        this.rows = rows;
        this.cols = cols;
        this.setPrefSize(width, height);
        this.tileSize = calculateTileSize(width * 0.8, height * 0.8, rows, cols);
        this.playerName = playerName;
        this.difficulty = difficulty;

        // Laad de afbeeldingen
            bushImage = new Image("file:src/be/kdg/labyrinth/Bush.jpg");
            pathImage = new Image("file:src/be/kdg/labyrinth/Path.jpg");
            startImage = new Image("file:src/be/kdg/labyrinth/Start.png");
            caveImage = new Image("file:src/be/kdg/labyrinth/Cave.png");
            flagImage = new Image("file:src/be/kdg/labyrinth/Flag.jpg");
            playerImage = new Image("file:src/be/kdg/labyrinth/Player.png");


        this.canvas = new Canvas(cols * tileSize, rows * tileSize); //canvas is een afbeelding waar je eigenlijk op kunt tekenen
        this.gc = canvas.getGraphicsContext2D(); //de graphicscontext zorgt ervoor dat je op de canvas kunt tekenen

        initializeNodes(playerName);
        layoutNodes();

        this.widthProperty().addListener((obs, oldVal, newVal) -> resizeCanvas()); //zorgt ervoor dat het labyrinth responsive is.
        this.heightProperty().addListener((obs, oldVal, newVal) -> resizeCanvas()); //zorgt ervoor dat het labyrinth responsive is.

        loadHighscores();
    }

    private void resizeCanvas() {
        double newWidth = this.getWidth();
        double newHeight = this.getHeight();
        tileSize = calculateTileSize(newWidth * 0.8, newHeight * 0.8, rows, cols);
        canvas.setWidth(cols * tileSize);
        canvas.setHeight(rows * tileSize);
    }

    private int calculateTileSize(double width, double height, int rows, int cols) {
        int tileWidth = (int) (width / cols);
        int tileHeight = (int) (height / rows);
        return Math.min(tileWidth, tileHeight) - 5;
    }

    private void initializeNodes(String playerName) {
        titleLabel = new Label("Welkom bij het labyrinth " + playerName);
        titleLabel.setStyle("-fx-font-size: 50px; " +
                "-fx-font-family: 'Berlin Sans FB'; " +
                "-fx-font-weight: bold; " +
                "-fx-text-fill: white; " +
                "-fx-background-color: rgba(0, 0, 0, 0.5); " +
                "-fx-background-radius: 5px;");

        timeLabel = new Label("Tijd: 00:00:00");
        timeLabel.setStyle("-fx-font-size: 35px; " +
                "-fx-text-fill: white; " +
                "-fx-background-color: rgba(0, 0, 0, 0.5); " +
                "-fx-background-radius: 5px;");

        playerPositionLabel = new Label("Spelerpositie: (0, 0)");
        playerPositionLabel.setStyle("-fx-font-size: 35px; " +
                "-fx-text-fill: white; " +
                "-fx-background-color: rgba(0, 0, 0, 0.5); " +
                "-fx-background-radius: 5px;");

        keyPressedLabel = new Label("Ingedrukt toets: ");
        keyPressedLabel.setStyle("-fx-font-size: 35px; " +
                "-fx-text-fill: white; " +
                "-fx-background-color: rgba(0, 0, 0, 0.5); " +
                "-fx-background-radius: 5px;");

        scoresLabel = new Label("Highscores:\nGeen highscores beschikbaar");
        scoresLabel.setStyle("-fx-font-size: 20px; " +
                "-fx-text-fill: white; " +
                "-fx-background-color: rgba(0, 0, 0, 0.5); " +
                "-fx-background-radius: 5px;");

        // Initialiseer de terugknop
        backButton = new Button("Terug naar Start");
        backButton.setStyle(
                "-fx-font-size: 20px; " +
                        "-fx-font-family: 'Berlin Sans FB'; " +
                        "-fx-padding: 10px; " +
                        "-fx-min-width: 150px; " +
                        "-fx-min-height: 50px; " +
                        "-fx-border-color: white; " +
                        "-fx-border-radius: 10px; " +
                        "-fx-border-width: 2px; " +
                        "-fx-text-fill: white; " +
                        "-fx-background-color: transparent; " +
                        "-fx-background-insets: 0; " +
                        "-fx-background-radius: 10px;"
        );

        menuBar = new MenuBar();
        Menu menu = new Menu("Menu");
        aboutMenuItem = new MenuItem("About");
        tutorialMenuItem = new MenuItem("Tutorial");
        menu.getItems().add(aboutMenuItem);
        menu.getItems().add(tutorialMenuItem);
        menuBar.getMenus().add(menu);
    }

    private void layoutNodes() {
        Image backgroundImage = new Image("file:src/be/kdg/labyrinth/Land.jpg"); //image gebruik je om de afbeelding op te halen uit een bestand
        ImageView backgroundView = new ImageView(backgroundImage); //imageview wordt gebruikt om de afbeelding te laten tonen op de UI
        backgroundView.setFitWidth(this.getWidth());
        backgroundView.setFitHeight(this.getHeight());

        this.widthProperty().addListener((obs, oldVal, newVal) -> backgroundView.setFitWidth(newVal.doubleValue())); //zorgt ervoor dat de achtergrond responsive is
        this.heightProperty().addListener((obs, oldVal, newVal) -> backgroundView.setFitHeight(newVal.doubleValue())); //zorgt ervoor dat de achtergrond responsive is
        //this verwijst naar het huidige object
        //de widthProperty verwijst naar de huidige breedte van de borderpane.
        //elke keer als je de breedte aanpast wordt de listener aangeroepen, de lambda is de listener waarop die wordt uitgevoerd
        //De listener zorgt ervoor dat je programma reageert op automatische veranderingen
        //obs observable property (widthProperty)
        //oldval is de oude waarde van de breedte
        // newval is de nieuwe waarde van de breedte
        //background.setFitWidth past de breedte op basis van de nieuwe waarde

        Region overlay = new Region(); //dit is eigenlijk een lege container. Word gebruikt voor effects
        overlay.setStyle("-fx-background-color: rgba(0, 0, 0, 0.5);");

        StackPane backgroundPane = new StackPane(backgroundView, overlay);
        backgroundPane.setAlignment(Pos.CENTER);

        VBox topBox = new VBox(25); // je kan hier naast de 25 ook de titleLabel en playerpositionLabel schrijven ipv getchildren
        topBox.setAlignment(Pos.CENTER);
        topBox.getChildren().addAll(menuBar, titleLabel, playerPositionLabel, keyPressedLabel);

        VBox topRightBox = new VBox(10);
        topRightBox.setAlignment(Pos.TOP_RIGHT);
        topRightBox.getChildren().addAll(timeLabel);

        VBox leftBox = new VBox(10, scoresLabel);
        leftBox.setAlignment(Pos.TOP_LEFT);

        StackPane centerPane = new StackPane(canvas);
        centerPane.setAlignment(Pos.CENTER);

        // VBox voor de terugknop onder het labyrint
        VBox bottomBox = new VBox(10);
        bottomBox.setAlignment(Pos.CENTER);
        bottomBox.getChildren().add(backButton);

        BorderPane mainPane = new BorderPane(); //eigenlijk is dit overbodig omdat je gameview al de borderpane extend
        mainPane.setTop(topBox);
        mainPane.setRight(topRightBox);
        mainPane.setLeft(leftBox);
        mainPane.setCenter(centerPane);
        mainPane.setBottom(bottomBox);

        StackPane rootPane = new StackPane(backgroundPane, mainPane); //hier gebruiken we stackpane om ervoor dat alles zichtbaar is.

        this.setCenter(rootPane);
    }

    private void loadHighscores() {
        List<String> highscores = new ArrayList<>();
        String fileName = "src/be/kdg/labyrinth/Highscores" + difficulty + ".txt";

        try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
            String line;
            while ((line = reader.readLine()) != null) {
                highscores.add(line);
            }
        } catch (IOException e) {
            System.err.println("Error loading highscores for " + difficulty + ": " + e.getMessage());
        }

        StringBuilder formattedHighscores = new StringBuilder("Highscores (" + difficulty + "):\n");
        if (highscores.isEmpty()) {
            formattedHighscores.append("Geen highscores beschikbaar");
        } else {
            for (String highscore : highscores) {
                formattedHighscores.append(highscore).append("\n");
            }
        }

        scoresLabel.setText(formattedHighscores.toString());
    }

    public void drawTile(int row, int col, char tile) {
        gc.drawImage(pathImage, col * tileSize, row * tileSize, tileSize, tileSize);

        Image overlayImage = switch (tile) {
            case '#' -> bushImage;
            case 'S' -> startImage;
            case 'O' -> caveImage;
            case 'E' -> flagImage;
            default -> null;
        };

        if (overlayImage != null) {
            gc.drawImage(overlayImage, col * tileSize, row * tileSize, tileSize, tileSize);
        }
    }

    public void drawPlayer(int row, int col) {
        if (playerImage != null) {
            gc.drawImage(playerImage, col * tileSize, row * tileSize, tileSize, tileSize);
        } else {
            System.err.println("Spelerafbeelding is niet geladen!");
        }
    }

    public void drawTrail(int row, int col) {
        gc.drawImage(pathImage, col * tileSize, row * tileSize, tileSize, tileSize);
    }

    public void updateTime(String time) {
        timeLabel.setText("Tijd: " + time);
    }

    public void updatePlayerPosition(int row, int col) {
        playerPositionLabel.setText("Spelerpositie: (" + row + ", " + col + ")");
    }

    public void updateKeypressedLabel(String key){
        keyPressedLabel.setText("Ingedrukte toets: "+ key);
    }

    public String getPlayerName() {
        return playerName;
    }

    // Getter voor de terugknop
    public Button getBackButton() {
        return backButton;
    }

    public MenuItem getAboutMenuItem() {
        return  aboutMenuItem;
    }

    public MenuItem getTutorialMenuItem(){
        return  tutorialMenuItem;
    }
}