package org.example.mesosll07;

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class DeckGridApp extends Application {

    // Inizializza il Logger
    private static final Logger logger = LogManager.getLogger(DeckGridApp.class);

    private PDDocument document;
    private PDFRenderer pdfRenderer;
    private int totalCards = 0;

    // Contenitori per le tre righe
    private HBox topRow;
    private HBox centerRow;
    private HBox bottomRow;
    private Button btnShuffle;

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Tavolo da Gioco - Carte Casuali");
        logger.info("Avvio dell'applicazione JavaFX");

        // Pulsanti
        Button btnLoad = new Button("Carica PDF Mazzo");
        btnShuffle = new Button("Rimescola Carte");
        btnShuffle.setDisable(true); // Disabilitato finché non si carica un PDF

        btnLoad.setOnAction(e -> loadPdf(primaryStage));
        btnShuffle.setOnAction(e -> distributeRandomCards());

        HBox topMenu = new HBox(15, btnLoad, btnShuffle);
        topMenu.setAlignment(Pos.CENTER);
        topMenu.setPadding(new Insets(10));

        // Setup delle tre righe (spazio tra le carte impostato a 10px)
        topRow = createRowContainer();
        centerRow = createRowContainer();
        bottomRow = createRowContainer();

        // Contenitore verticale per le righe
        VBox tableArea = new VBox(30,
                new Label("TOP (8 Carte):"), topRow,
                new Label("CENTER (6 Carte):"), centerRow,
                new Label("BOTTOM (7 Carte):"), bottomRow
        );
        tableArea.setAlignment(Pos.CENTER);
        tableArea.setPadding(new Insets(20));

        // Mettiamo il tavolo in uno ScrollPane nel caso le carte siano troppo grandi per lo schermo
        ScrollPane scrollPane = new ScrollPane(tableArea);
        scrollPane.setFitToWidth(true);

        BorderPane root = new BorderPane();
        root.setTop(topMenu);
        root.setCenter(scrollPane);

        // Finestra un po' più grande per contenere tutte queste carte
        Scene scene = new Scene(root, 1200, 800);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private HBox createRowContainer() {
        HBox row = new HBox(15); // 15px di spazio tra una carta e l'altra
        row.setAlignment(Pos.CENTER);
        return row;
    }

    private void loadPdf(Stage stage) {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Seleziona il PDF del mazzo di carte");
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("File PDF", "*.pdf"));
        File file = fileChooser.showOpenDialog(stage);

        if (file != null) {
            try {
                if (document != null) {
                    document.close();
                }
                logger.info("Caricamento file PDF: {}", file.getAbsolutePath());
                document = PDDocument.load(file);
                pdfRenderer = new PDFRenderer(document);
                totalCards = document.getNumberOfPages();

                logger.info("PDF caricato. Pagine totali (carte): {}", totalCards);
                btnShuffle.setDisable(false);

                // Distribuisci le carte per la prima volta
                distributeRandomCards();

            } catch (IOException e) {
                logger.error("Errore nel caricamento del PDF", e);
            }
        }
    }

    private void distributeRandomCards() {
        if (document == null || totalCards == 0) return;

        logger.info("Inizio rimescolamento e distribuzione carte...");

        // Pulisce il tavolo dalle carte precedenti
        topRow.getChildren().clear();
        centerRow.getChildren().clear();
        bottomRow.getChildren().clear();

        // 1. Crea una lista con tutti gli indici (da 0 al numero totale di pagine)
        List<Integer> deckIndices = new ArrayList<>();
        for (int i = 0; i < totalCards; i++) {
            deckIndices.add(i);
        }

        // 2. Mescola la lista (Simula la mescolata del mazzo)
        Collections.shuffle(deckIndices);

        // 3. Distribuisci nelle righe (evitando IndexOutOfBounds se il PDF ha meno di 21 pagine)
        // Riga Top: 8 carte
        populateRow(topRow, deckIndices, 0, 8);

        // Riga Center: 6 carte
        populateRow(centerRow, deckIndices, 8, 6);

        // Riga Bottom: 7 carte
        populateRow(bottomRow, deckIndices, 14, 7);

        logger.info("Distribuzione completata.");
    }

    private void populateRow(HBox row, List<Integer> deckIndices, int startIndex, int numberOfCards) {
        for (int i = 0; i < numberOfCards; i++) {
            int actualIndex = startIndex + i;

            // Se abbiamo esaurito le carte nel PDF, interrompiamo
            if (actualIndex >= deckIndices.size()) {
                logger.warn("Il PDF non ha abbastanza carte per riempire questa riga.");
                break;
            }

            int pageNumber = deckIndices.get(actualIndex);
            ImageView cardImage = createCardImageView(pageNumber);

            if (cardImage != null) {
                row.getChildren().add(cardImage);
            }
        }
    }

    private ImageView createCardImageView(int pageIndex) {
        try {
            // Renderizza la pagina. Usiamo 100 DPI invece di 150 per risparmiare RAM,
            // dato che ora stiamo generando 21 immagini contemporaneamente.
            BufferedImage bim = pdfRenderer.renderImageWithDPI(pageIndex, 100);
            Image fxImage = SwingFXUtils.toFXImage(bim, null);

            ImageView imageView = new ImageView(fxImage);
            // Impostiamo l'altezza fissa per le carte, in modo che stiano sullo schermo
            imageView.setFitHeight(180);
            imageView.setPreserveRatio(true);
            imageView.setStyle("-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.5), 5, 0, 0, 0);");

            return imageView;
        } catch (IOException e) {
            logger.error("Errore durante il rendering della pagina {}", pageIndex, e);
            return null;
        }
    }

    @Override
    public void stop() throws Exception {
        if (document != null) {
            document.close();
            logger.info("Documento PDF chiuso correttamente.");
        }
        logger.info("Applicazione terminata.");
        super.stop();
    }

    public static void main(String[] args) {
        launch(args);
    }
}