package tourplaner.ui;

import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import tourplaner.business.ConfigHelper;
import tourplaner.business.EinheitenAdder;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.LocalDate;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

public class AlertHelper {

    /**
     * Warning Dialog
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     */
    public static void warn(String title, String header, String msg){
        alertType(Alert.AlertType.WARNING, title, header, msg);
    }

    /**
     * Info Dialog
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     */
    public static void inform(String title, String header, String msg){
        alertType(Alert.AlertType.INFORMATION, title, header, msg);
    }

    /**
     * Info Dialog ohne Header
     * @param title Title des Dialogs
     * @param msg Nachricht des Dialogs
     */
    public static void informNoHeader(String title, String msg){
        inform(title, null, msg);
    }

    /**
     * Error Dialog
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     */
    public static void error(String title, String header, String msg){
        alertType(Alert.AlertType.ERROR, title, header, msg);
    }

    /**
     * Ausgabe einer Exception in einem Dialog
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     * @param ex Die exception die ausgegeben werden soll
     */
    public static void exerror(String title, String header, String msg, Exception ex){
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setTitle(title);
        alert.setHeaderText(header);
        alert.setContentText(msg);
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        String exceptionText = sw.toString();
        Label label = new Label(ConfigHelper.getLangIniString("exceptionstackheader"));
        TextArea textArea = new TextArea(exceptionText);
        textArea.setEditable(false);
        textArea.setWrapText(true);
        textArea.setMaxWidth(Double.MAX_VALUE);
        textArea.setMaxHeight(Double.MAX_VALUE);
        GridPane.setVgrow(textArea, Priority.ALWAYS);
        GridPane.setHgrow(textArea, Priority.ALWAYS);
        GridPane expContent = new GridPane();
        expContent.setMaxWidth(Double.MAX_VALUE);
        expContent.add(label, 0, 0);
        expContent.add(textArea, 0, 1);
        alert.getDialogPane().setExpandableContent(expContent);
        alert.showAndWait();
    }

    /**
     *
     * @param alertly Typ des Dialogs
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     */
    private static void alertType(Alert.AlertType alertly, String title, String header, String msg){
        Alert alert = new Alert(alertly);
        alert.setTitle(title);
        alert.setHeaderText(header);
        alert.setContentText(msg);
        Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
        stage.getIcons().add(
                new Image("file:"+ ConfigHelper.getIniString(ConfigHelper.getStandartConfig(), "start", "logo")));
        alert.showAndWait();
    }

    /**
     * Texteingabe die nicht leer sein darf
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     * @return Null bei keiner eingabe
     */
    public static String inputText(String title, String header, String msg, String content){
        return inputTextNotNull(title, header, msg, content, true);
    }

    /**
     * Texteingabe
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     * @param notNull true wenn der input nicht leer sein darf
     * @return Null bei keiner eingabe
     */
    public static String inputTextNotNull(String title, String header, String msg, String content, boolean notNull) {
        String returnStr = null;
        while (returnStr == null) {
            Optional<String> result = inputHelper(title, header, msg, content);

            AtomicReference<String> returnText = new AtomicReference<>("");
            if(result.isPresent()) {
                result.ifPresent(returnText::set);
                returnStr = returnText.get();
                if (returnStr.isEmpty() && notNull) {
                    AlertHelper.warn(ConfigHelper.getLangIniString("tournametitle"),
                            ConfigHelper.getLangIniString("achtung"),
                            ConfigHelper.getLangIniString("keintextimfeld"));
                }
            }else{
                return "";
            }
        }
        return returnStr;
    }

    /**
     * Erstellt einen Text Input Dialog
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     * @return Result des Inputs
     */
    private static Optional<String> inputHelper(String title, String header, String msg, String content){
        TextInputDialog dialog = new TextInputDialog(content);
        dialog.setTitle(title);
        dialog.setHeaderText(header);
        dialog.setContentText(msg);

        Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
        stage.getIcons().add(
                new Image("file:"+ ConfigHelper.getIniString(ConfigHelper.getStandartConfig(), "start", "logo")));

        return dialog.showAndWait();

    }


    /**
     * Positive Nummer eingabe. Wenn Convertierung zu int nicht klappt -> -1
     * @param title Title des Dialogs
     * @param header Header des Dialogs
     * @param msg Nachricht des Dialogs
     * @return -1.0 bei error sonst ein double
     */
    public static double inputNumber(String title, String header, String msg, String content) {
        double returnDouble = -2.0;
        while (returnDouble < -1.0) {
            Optional<String> result = inputHelper(title, header, msg, content);
            AtomicReference<Double> returnText = new AtomicReference<Double>(-1.0);
            result.ifPresent(s -> {
                try {
                    double resultDouble = Double.parseDouble(result.get());
//                    int resultInt = Integer.parseInt(result.get());
                    returnText.set(resultDouble);
                    if (resultDouble < 0){
                        AlertHelper.warn(title, ConfigHelper.getLangIniString("achtung"), ConfigHelper.getLangIniString("nurpositivezahlen"));
                    }
                } catch (NumberFormatException e) {
                    AlertHelper.warn(title, ConfigHelper.getLangIniString("achtung"), ConfigHelper.getLangIniString("nurzahlen"));
                    returnText.set(-2.0);
                }

            });
            returnDouble = returnText.get();
        }
        return returnDouble;
    }

    /**
     * Date Picker Dialog, sobald ein Datum ausgewählt wurde, wird es automatisch bestätigt und der dialog geschlossen
     * @param content Aktuelles datum
     * @return Gewähltes datum
     */
    public static LocalDate datePicker(LocalDate content){
        final DatePicker datePicker = new DatePicker(content);
        final Stage stage = new Stage();
        stage.getIcons().add(
                new Image("file:"+ ConfigHelper.getIniString(ConfigHelper.getStandartConfig(), "start", "logo")));
        AtomicReference<LocalDate> selectedDate = new AtomicReference<>();
        stage.setOnCloseRequest(ev -> {
           stage.close();
        });

        datePicker.setOnAction(event -> {
            LocalDate date = datePicker.getValue();
            System.out.println("Selected date: " + date);
            selectedDate.set(date);
            stage.close();
        });

        stage.setScene(
                new Scene(datePicker)
        );
        stage.showAndWait();
        return selectedDate.get();
    }


    /**
     * File Auswahl
     * @param btn Text des Speichern/Öffnen Btn
     * @return String des Files, bei error null
     */
    public static String fileChooser(String btn){
        // JFileChooser-Objekt erstellen
        JFileChooser chooser = new JFileChooser();
        // Dialog zum Oeffnen von Dateien anzeigen
        int rueckgabeWert = chooser.showDialog(null, btn);

        /* Abfrage, ob auf "Öffnen" geklickt wurde */
        if(rueckgabeWert == JFileChooser.APPROVE_OPTION)
        {
            return chooser.getSelectedFile().getAbsolutePath();
        }
        return null;
    }
}
