package sd.dashboard;

import javafx.geometry.Insets;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.Spinner;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;

/**
 * Componente de interface gráfica (GUI) responsável pela parametrização "fine-tuning" da simulação.
 * <p>
 * Esta classe apresenta um diálogo modal que permite ao operador sobrepor (override)
 * as configurações estáticas carregadas do ficheiro {@code .properties} imediatamente
 * antes da execução. Oferece controlo granular sobre:
 * <ul>
 * <li><b>Geração de Carga:</b> Alternância entre modelos estocásticos (Poisson) e determinísticos.</li>
 * <li><b>Temporização:</b> Ajuste da escala de tempo (Time Scale) para visualização vs. performance pura.</li>
 * <li><b>Mix de Veículos:</b> Definição das probabilidades de geração por tipo de agente.</li>
 * </ul>
 */
public class ConfigurationDialog {

    /**
     * Exibe o diálogo de configuração avançada e captura as intenções do utilizador.
     * <p>
     * A interface é construída dinamicamente usando layouts JavaFX ({@link GridPane}, {@link VBox}).
     * Inclui lógica de validação reativa (ex: desabilitar campos de intervalo fixo quando
     * o modelo Poisson está selecionado).
     * * 

[Image of Poisson distribution graph]

     *
     * @param owner A janela pai (Stage) para bloquear a interação até o fecho do diálogo (Modalidade).
     * @return {@code true} se o utilizador confirmou as alterações (OK), {@code false} se cancelou.
     */
    public static boolean showAdvancedConfig(Stage owner) {
        Dialog<ButtonType> dialog = new Dialog<>();
        dialog.initOwner(owner);
        dialog.initModality(Modality.APPLICATION_MODAL);
        dialog.setTitle("Configuração Avançada da Simulação");
        dialog.setHeaderText("Ajustar parâmetros da simulação");

        // Criar painel de configuração
        VBox content = new VBox(15);
        content.setPadding(new Insets(20));
        content.setStyle("-fx-background-color: #2b2b2b;");

        // Seção 1: Parâmetros de Chegada
        Label arrivalHeader = new Label("Parâmetros de Chegada de Veículos");
        arrivalHeader.setStyle("-fx-font-weight: bold; -fx-font-size: 14px; -fx-text-fill: white;");
        
        GridPane arrivalGrid = new GridPane();
        arrivalGrid.setHgap(10);
        arrivalGrid.setVgap(10);
        arrivalGrid.setPadding(new Insets(10));

        // Modelo de chegada
        Label modelLabel = new Label("Modelo de chegada:");
        modelLabel.setStyle("-fx-text-fill: white;");
        ComboBox<String> modelCombo = new ComboBox<>();
        modelCombo.getItems().addAll("POISSON", "FIXED");
        modelCombo.setValue("POISSON");
        arrivalGrid.add(modelLabel, 0, 0);
        arrivalGrid.add(modelCombo, 1, 0);

        // Taxa de chegada (λ)
        Label rateLabel = new Label("Taxa de chegada (λ) [veículos/s]:");
        rateLabel.setStyle("-fx-text-fill: white;");
        Spinner<Double> rateSpinner = new Spinner<>(0.1, 2.0, 0.5, 0.1);
        rateSpinner.setEditable(true);
        rateSpinner.setPrefWidth(100);
        arrivalGrid.add(rateLabel, 0, 1);
        arrivalGrid.add(rateSpinner, 1, 1);

        // Intervalo fixo (se aplicável)
        Label intervalLabel = new Label("Intervalo fixo [s]:");
        intervalLabel.setStyle("-fx-text-fill: white;");
        Spinner<Double> intervalSpinner = new Spinner<>(0.5, 10.0, 2.0, 0.5);
        intervalSpinner.setEditable(true);
        intervalSpinner.setPrefWidth(100);
        intervalSpinner.setDisable(true);
        arrivalGrid.add(intervalLabel, 0, 2);
        arrivalGrid.add(intervalSpinner, 1, 2);

        // Habilitar/desabilitar intervalo baseado no modelo
        modelCombo.setOnAction(e -> {
            boolean isFixed = "FIXED".equals(modelCombo.getValue());
            intervalSpinner.setDisable(!isFixed);
            rateSpinner.setDisable(isFixed);
        });

        // Seção 2: Parâmetros de Tempo
        Label timeHeader = new Label("Parâmetros de Tempo");
        timeHeader.setStyle("-fx-font-weight: bold; -fx-font-size: 14px; -fx-text-fill: white;");
        
        GridPane timeGrid = new GridPane();
        timeGrid.setHgap(10);
        timeGrid.setVgap(10);
        timeGrid.setPadding(new Insets(10));

        // Duração da simulação
        Label durationLabel = new Label("Duração da simulação [s]:");
        durationLabel.setStyle("-fx-text-fill: white;");
        Spinner<Integer> durationSpinner = new Spinner<>(60, 7200, 300, 60);
        durationSpinner.setEditable(true);
        durationSpinner.setPrefWidth(100);
        timeGrid.add(durationLabel, 0, 0);
        timeGrid.add(durationSpinner, 1, 0);

        // Escala temporal (para visualização)
        Label scaleLabel = new Label("Escala temporal (0=instantâneo, 1=tempo real):");
        scaleLabel.setStyle("-fx-text-fill: white;");
        Spinner<Double> scaleSpinner = new Spinner<>(0.0, 1.0, 0.01, 0.01);
        scaleSpinner.setEditable(true);
        scaleSpinner.setPrefWidth(100);
        timeGrid.add(scaleLabel, 0, 1);
        timeGrid.add(scaleSpinner, 1, 1);

        // Tempo de drenagem
        Label drainLabel = new Label("Tempo de drenagem [s]:");
        drainLabel.setStyle("-fx-text-fill: white;");
        Spinner<Integer> drainSpinner = new Spinner<>(0, 300, 60, 10);
        drainSpinner.setEditable(true);
        drainSpinner.setPrefWidth(100);
        timeGrid.add(drainLabel, 0, 2);
        timeGrid.add(drainSpinner, 1, 2);

        // Seção 3: Distribuição de Tipos de Veículos
        Label vehicleHeader = new Label("Distribuição de Tipos de Veículos");
        vehicleHeader.setStyle("-fx-font-weight: bold; -fx-font-size: 14px; -fx-text-fill: white;");
        
        GridPane vehicleGrid = new GridPane();
        vehicleGrid.setHgap(10);
        vehicleGrid.setVgap(10);
        vehicleGrid.setPadding(new Insets(10));

        Label bikeLabel = new Label("Bicicletas/Motos [%]:");
        bikeLabel.setStyle("-fx-text-fill: white;");
        Spinner<Integer> bikeSpinner = new Spinner<>(0, 100, 10, 5);
        bikeSpinner.setEditable(true);
        bikeSpinner.setPrefWidth(100);
        vehicleGrid.add(bikeLabel, 0, 0);
        vehicleGrid.add(bikeSpinner, 1, 0);

        Label lightLabel = new Label("Veículos Ligeiros [%]:");
        lightLabel.setStyle("-fx-text-fill: white;");
        Spinner<Integer> lightSpinner = new Spinner<>(0, 100, 70, 5);
        lightSpinner.setEditable(true);
        lightSpinner.setPrefWidth(100);
        vehicleGrid.add(lightLabel, 0, 1);
        vehicleGrid.add(lightSpinner, 1, 1);

        Label heavyLabel = new Label("Veículos Pesados [%]:");
        heavyLabel.setStyle("-fx-text-fill: white;");
        Spinner<Integer> heavySpinner = new Spinner<>(0, 100, 20, 5);
        heavySpinner.setEditable(true);
        heavySpinner.setPrefWidth(100);
        vehicleGrid.add(heavyLabel, 0, 2);
        vehicleGrid.add(heavySpinner, 1, 2);

        // Nota informativa
        Label noteLabel = new Label("Nota: Estes parâmetros sobrepõem os valores do ficheiro .properties selecionado.\n" +
                                    "Para usar os valores padrão do ficheiro, deixe em branco ou cancele.");
        noteLabel.setWrapText(true);
        noteLabel.setStyle("-fx-font-size: 11px; -fx-text-fill: #aaaaaa;");

        // Adicionar tudo ao conteúdo
        content.getChildren().addAll(
            arrivalHeader, arrivalGrid,
            new Separator(),
            timeHeader, timeGrid,
            new Separator(),
            vehicleHeader, vehicleGrid,
            new Separator(),
            noteLabel
        );

        dialog.getDialogPane().setContent(content);
        dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);

        // Mostrar diálogo e processar resultado
        return dialog.showAndWait()
                .map(buttonType -> buttonType == ButtonType.OK)
                .orElse(false);
    }
}