package com.example.happy_bird;

import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.ImagePattern;
import javafx.stage.Stage;
import javafx.scene.shape.*;
import javafx.util.Duration;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;

public class HappyBirdMain extends Application {

    private float velocity = 0f;
    private float gravity = 0.25f;
    private int birdPositionMovedBy = 0;
    private int collectedPoints;
    private int playerhighscore;
    private boolean openEndScreen = false;
    private boolean endScreenOpened = false;

    /* Formatierungsklasse */
    private final FormatingClass formatingClass = new FormatingClass();

    /* Datenbank einlesen */
    private final MariaDB datenbank = new MariaDB();

    /* Panes erstellen und zuweisen */
    private final Pane pane = new Pane();
    private final Pane pause = new Pane();
    private final Pane endScreen = new Pane();

    /* Scene erstellen und zuweisen */
    private final Scene scene = new Scene(pane, 800, 700);

    /* Labels erstellen und zuweisen */
    private final Label nameLabel = new Label("NAME");
    private final Label acronymLabel = new Label("KÜRZEL");
    private final Label headline = new Label("HAPPY BIRD");
    private final Label soundLabel = new Label("SOUND");
    private final Label currentScoreLabel = new Label("SCORE: " + collectedPoints);
    private final Label highscoreLabel = new Label("HIGHSCORE: ");
    private final Label pauseMenuLabel = new Label("PAUSE");
    private final Label soundLabelPause = new Label("SOUND");
    private final Label highscoreMenuLabel = new Label();
    private final Label currentScoreEndscreenLabel = new Label("YOUR SCORE: ");
    private final Label endScreenHeadline = new Label("GAME OVER");
    private final Label checkNameLabel = new Label("");
    private final Label checkAcronymLabel = new Label("");

    /*Labels in Arrays speichern*/
    private final Label[] labels = {nameLabel, acronymLabel, soundLabel, currentScoreLabel,
            highscoreLabel, highscoreMenuLabel, checkAcronymLabel, checkNameLabel};
    private final Label[] headlineLabels = {headline};

    /*Buttons erstellen und zuweisen*/
    private final Button startButton = new Button("START");
    private final Button highscoresButton = new Button("HIGHSCORES");
    private final Button settingsButton = new Button("EINSTELLUNGEN");
    private final Button startGameButton = new Button("SPIEL STARTEN");
    private final Button menuButton = new Button("ZURÜCK");
    private final Button pauseButton = new Button("PAUSE");
    private final Button continueButton = new Button("WEITERSPIELEN");
    private final Button settingsButtonPause = new Button("EINSTELLUNGEN");
    private final Button menuButtonPause = new Button("HAUPTMENÜ");
    private final Button backButtonPause = new Button("ZURÜCK");
    private final Button background1 = new Button();
    private final Button background2 = new Button();
    private final Button backMenuButton = new Button("HAUPTMENÜ");
    private final Button restartGameButton = new Button("NEU STARTEN");
    private final Button personalHighscoresButton = new Button ("YOUR SCORES");
    private final Button backEndscreenButton = new Button("ZURÜCK");

    /*Buttons in Arrays speichern*/
    private final Button[] buttons = {startButton, highscoresButton, settingsButton, startGameButton,
            menuButton, pauseButton, continueButton, settingsButtonPause, menuButtonPause,
            backButtonPause, backMenuButton, restartGameButton, personalHighscoresButton, backEndscreenButton};
    private final Button[] pauseButtons = {continueButton, settingsButtonPause, menuButtonPause, backButtonPause};
    private final Button[] backgroundButtons = {background1, background2};
    private final Button[] endscreenButtons = {backMenuButton, restartGameButton,
            personalHighscoresButton, backEndscreenButton};

    /*Textfelder erstellen und zuweisen*/
    private final TextField name = new TextField();
    private final TextField acronym = new TextField();

    /*Textfelder in Arrays speichern*/
    private final TextField[] inputFields = {name, acronym};

    /*Slider erstellen und zuweisen*/
    private final Slider soundSlider = new Slider();
    private final Slider soundSliderPause = new Slider();

    /*Bilder*/
    private final Image bird = new Image("file:src/main/resources/com/example/happy_bird/pics/bird.png");

    private final Image pipeTop = new Image("file:src/main/resources/com/example/happy_bird/pics/PipeTop.png");
    private final Image pipeBottom = new Image("file:src/main/resources/com/example/happy_bird/pics/PipeBottom.png");

    /*Variablen für den Spielverlauf*/
    //menuScreenRunning: das Hauptmenü ist aufgerufen
    private boolean menuScreenRunning;
    //gameRunning: das Spiel läuft/ GameScreen ist aufgerufen
    private boolean gameRunning;

    /*TranslateTransitions für obere und untere Pipes*/
    private TranslateTransition top;
    private TranslateTransition bottom;

    /*ArrayList, in die alle Transitions gespeichert werden*/
    private final ArrayList<Transition> transitions = new ArrayList<Transition>();

    /*Rechteck für den Bird*/
    private Rectangle happyBird;

    /*ArrayList, in der alle Rechtecke/ Pipes gespeichert werden*/
    private final ArrayList<Rectangle> pipesArrayList = new ArrayList<Rectangle>();
    private final ArrayList<Rectangle> pipesToRemove = new ArrayList<Rectangle>();

    /*Timeline, auf der sich die Pipes und der Vogel abspielen*/
    private Timeline timeline;

    /*AnimationTimer checkt im Spielverlauf, ob eine Pipe mit dem Bird kollidiert*/
    private AnimationTimer collisionChecker;


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

    /** alle */
    @Override
    public void start(Stage stage) {
        stage.setTitle("Happy Bird");
        stage.setScene(scene);
        generateMenueScreen();

        /*ClickEvents:*/
        startButton.setOnAction(event -> startButtonClick());

        settingsButton.setOnAction(event -> settingsButtonClick());

        highscoresButton.setOnAction(event -> highscoresButtonClick());

        menuButton.setOnAction(event -> menuButtonClick());

        startGameButton.setOnAction(event ->  {
            gameRunning = true;
            startGameButtonClick();
        });

        stage.show();
    }

    /*** Alteköster
     * Erstellt den Bird als Rectangle mit einem Bild.
     * @return happyBird    ein Rectangle
     */
    public Rectangle createBird() {
        /* Startposition des Birds */
        int x = 50;
        int y = 325;

        /* Erstellen eines Rechtecks mit der passenden Größe */
        Rectangle happyBird = new Rectangle(x,y,45,30);

        /* Bild in das Rechteck setzen */
        happyBird.setFill(new ImagePattern(bird));

        /* View-Order auf 1 setzen, damit der Bird über den anderen Elementen auf dem Spielscreen liegt */
        happyBird.setStyle("-fx-view-order: 1");

        return happyBird;
    }

    /*** Alteköster
     * Erstellt zwei Pipes als Rectangle und fügt ihnen eine Animation über eine Transition hinzu
     * @return pipes    zwei Rectangles
     */
    public Rectangle[] createPipes() {

        /* y-Koordinate für die Pipes
         * -300, da die obere Pipe 500px hoch ist */
        int y = (int) (Math.random() * (200))-300;

        /* Pipe oben; spawnt bei x=900 -> 100 Pixel neben Bild */
        Rectangle topPipe = new Rectangle(900, y, 91, 500);

        /* Pipe unten; spawnt auf der gleichen Höhe wie obere Pipe
         * +400 +250, für Abstand zwischen oberer Pipe und unterer Pipe */
        Rectangle bottomPipe = new Rectangle(900, y + 400 + 250, 91, 500);

        /* Pipes in PipesArrayList schreiben */
        pipesArrayList.add(topPipe);
        pipesArrayList.add(bottomPipe);

        /* Pipes einen Hintergrundbild geben */
        topPipe.setFill(new ImagePattern(pipeTop));
        bottomPipe.setFill(new ImagePattern(pipeBottom));

        /* View-Order auf 1 setzen, damit die Pipe über den anderen Elementen auf dem Spielscreen liegt */
        topPipe.setStyle("-fx-view-order: 1");
        bottomPipe.setStyle("-fx-view-order: 1");

        /* neue Animationen über TranslateTransitions */
        top = new TranslateTransition();
        bottom = new TranslateTransition();

        /* Pipes den Transitions hinzufügen */
        top.setNode(topPipe);
        bottom.setNode(bottomPipe);

        /* die Pipes brauchen 7 Sekunden, bis sie von rechts nach links gelaufen ist */
        top.setDuration(Duration.seconds(7));
        bottom.setDuration(Duration.seconds(7));

        /* Pipe läuft 1100px nach links */
        top.setToX(-1100);
        bottom.setToX(-1100);


        /* nach Erreichen des linken Randes, wird die Pipe von Pane entfernt */
        top.setOnFinished(e -> {
            pane.getChildren().remove(topPipe);
        });
        bottom.setOnFinished(e -> {
            pane.getChildren().remove(bottomPipe);
        });

        /* Array für die Pipes */
        Rectangle[] pipes = {topPipe, bottomPipe};

        /* Transitions in ArrayList speichern, um sie nachher stoppen zu können */
        transitions.add(top);
        transitions.add(bottom);

        return pipes;
    }

    /*** alle
     * Generiert den GameScreen durch Ausblenden und
     * Sichtbarmachen der richtigen Buttons, Labels, ...
     */
    public void generateMenueScreen() {
        dataQuery();
        menuScreenRunning = true;

        /*Source als String*/
        String img = "file:src/main/resources/com/example/happy_bird/pics/Background0.png";

        /*Bild zu Hintergrund */
        BackgroundImage backgroundImage = formatingClass.backgroundFormating(img);

        /*Hintergrund zu Pane hinzufügen:*/
        Background background = new Background(backgroundImage);
        pane.setBackground(background);

        /*Labels formatieren:*/
        formatingClass.labelsFormating(labels, pane);
        formatingClass.headlineFormating(headlineLabels, pane);

        /*Überschrift umbenennen, falls aus anderem Screen*/
        headline.setText("HAPPY BIRD");

        /*alle labels an ihre Stelle:*/
        int yPositionLabels = 225;
        for (Label label : labels) {
            label.setLayoutX(275);
            label.setLayoutY(yPositionLabels);
            yPositionLabels += 150;
        }

        /*headline an ihre Stelle:*/
        headline.setLayoutX(250);
        headline.setLayoutY(100);
        headline.setVisible(true);

        /*soundLabel an seine Stelle:*/
        soundLabel.setLayoutY(225);

        /*Buttons formatieren:*/
        formatingClass.buttonsFormating(buttons, pane);

        /*alle Buttons an ihre Stelle:*/
        int yPositionButtons = 225;
        for (Button button : buttons) {
            button.setLayoutX(300);
            button.setLayoutY(yPositionButtons);
            yPositionButtons += 100;
            button.setVisible(true);
        }

        /*menuButton an seine Stelle und vorerst ausblenden:*/
        menuButton.setLayoutX(575);
        menuButton.setLayoutY(625);
        menuButton.setVisible(false);

        /*startGameButton unsichtbar*/
        startGameButton.setVisible(false);

        /*continueButton unsichtbar*/
        continueButton.setVisible(false);

        /*settingsButtonPause unsichtbar*/
        settingsButtonPause.setVisible(false);

        /*Buttons für Hintergründe*/
        formatingClass.backgroundButtonsFormating(backgroundButtons, pane);

        /*Background-Buttons unsichtbar*/
        background1.setVisible(false);
        background2.setVisible(false);

        /*Textfelder formatieren:*/
        formatingClass.textfieldsFormating(inputFields, pane);

        /*Textfelder an ihre Position:*/
        int yPositionInputFields = 290;
        for (TextField feld : inputFields) {
            feld.setLayoutX(275);
            feld.setLayoutY(yPositionInputFields);
            yPositionInputFields += 150;
        }

        /*SoundSlider anpassen:*/
        formatingClass.soundSliderFormating(soundSlider, pane);

    }

    /*** alle
     * Generiert den GameScreen durch Ausblenden und
     * Sichtbarmachen der richtigen Buttons, Labels, ...
     */
    public void generateGameScreen() {
        menuScreenRunning = false;
        playerhighscore = getPlayerHighscore();
        highscoreLabel.setText("HIGHSCORE: " + playerhighscore);
        /*Headline-Label umbenennen*/
        nameLabel.setText("KÜRZEL: " + acronym.getText());

        /*Textfelder ausblenden*/
        for(TextField feld : inputFields) {
            feld.setVisible(false);
        }

        /*Labels ausblenden*/
        for (Label label : labels ) {
            label.setVisible(false);
        }
        headline.setVisible(false);

        /*nameLabel positionieren und sichtbar machen*/
        nameLabel.setLayoutX(10);
        nameLabel.setLayoutY(10);
        nameLabel.setVisible(true);

        /*currentScoreLabel positionieren und sichtbar machen*/
        currentScoreLabel.setLayoutX(540);
        currentScoreLabel.setLayoutY(10);
        currentScoreLabel.setVisible(true);

        /*highscoreLabel positionieren und sichtbar machen*/
        highscoreLabel.setLayoutX(540);
        highscoreLabel.setLayoutY(70);
        highscoreLabel.setVisible(true);

        /*Pause-Button positionieren und sichtbar machen*/
        pauseButton.setLayoutX(575);
        pauseButton.setLayoutY(625);
        pauseButton.setVisible(true);

        /*übrige Buttons ausblenden*/
        startGameButton.setVisible(false);
        menuButton.setVisible(false);

        /** Alteköster */
        /*Timeline: alle 2 Sekunden spawnt eine neue Pipe am rechten Rand*/
        timeline = new Timeline(new KeyFrame(Duration.seconds(1.5), e ->{
            /*Pipes erstellen*/
            Rectangle[] pipesTopBottom = createPipes();

            /*Pipes der Pane hinzufügen*/
            for(Rectangle pipe : pipesTopBottom) {
                pane.getChildren().add(pipe);
            }
            /*Transitions abspielen*/
            top.play();
            bottom.play();
        }));

        happyBird = createBird();
        pane.getChildren().add(happyBird);

        timeline.setCycleCount(Animation.INDEFINITE);
        timeline.play();

        System.out.println("tl: "+timeline.getStatus());

        /** Alteköster, Bickmann, Pape*/
        collisionChecker = new AnimationTimer() {
            @Override
            public void handle(long timestamp) {
                if (!openEndScreen) {
                    for (Rectangle rectangle : pipesArrayList) {
                        if (rectangle != null) {
                            checkCollision(happyBird, rectangle);
                        }
                    }
                    for (Rectangle rectangle : pipesToRemove) {
                        pipesArrayList.remove(rectangle);
                    }
                } else if (endScreenOpened == false) {
                    writeIntoDatabase();
                    generateEndScreen();
                    endScreenOpened = true;
                }
            }
        };

        collisionChecker.start();

    }

    /*** Bickmann, Alteköster
     * Überprüft, ob eine Pipe mit dem Bird kollidiert
     * @param happyBird Rechteck mit dem Bird
     * @param pipe      Rechteck mit einer Pipe
     */
    public void checkCollision(Rectangle happyBird, Rectangle pipe) {
        /* Überprüft, ob der Vogel mit der Decke oder dem Boden kollidiert */
        if (happyBird.getLayoutY() > 330 || happyBird.getLayoutY() < -330) {
            /*Pausieren der Transitions/ Pipes*/
            for(Transition transition : transitions) {
                transition.pause();
            }

            /*Pausieren der Timeline, sodass keine neuen Pipes spawnen*/
            timeline.stop();
            gameRunning = false;
            openEndScreen = true;
        }
        /* Überprüft, ob eine der Grenzen des Rechtecks des Birds mit einer übergebenen Pipe kollidiert
         * wenn ja, hält das Spiel an bzw. wird beendet */
        if(happyBird.getBoundsInParent().intersects(pipe.getBoundsInParent())) {

            /*Pausieren der Transitions/ Pipes*/
            for(Transition transition : transitions) {
                transition.pause();
            }

            /*Pausieren der Timeline, sodass keine neuen Pipes spawnen*/
            timeline.stop();
            gameRunning = false;
            openEndScreen = true;
        }
        if(happyBird.getBoundsInParent().getMaxX() > pipe.getBoundsInParent().getMaxX()) {
            collectedPoints++;
            int pointsToSet = collectedPoints / 2;
            currentScoreLabel.setText("SCORE: " + pointsToSet);
            if (pointsToSet > playerhighscore) {
                highscoreLabel.setText("HIGHSCORE: " + pointsToSet);
            }
            pipesToRemove.add(pipe);
        }
    }


    /*** alle
     * Hauptmenü wird ausgeblendet, Nameneingabe folgt
     */
    public void startButtonClick() {
        /*Überschrift umbenennen*/
        headline.setText("START");
        nameLabel.setText("NAME");
        /*alle Buttons ausblenden*/
        for(Button button : buttons) {
            button.setVisible(false);
        }
        /*Label für Namenskonventionen*/
        checkNameLabel.setLayoutX(15);
        checkNameLabel.setLayoutY(290);

        /*Label für Kürzelkonventionen*/
        checkAcronymLabel.setLayoutX(15);
        checkAcronymLabel.setLayoutY(440);

        /*gebrauchte Buttons einblenden, ggf. anpassen*/
        menuButton.setVisible(true);
        startGameButton.setVisible(true);
        startGameButton.setLayoutY(520);

        /*Textfelder einblenden*/
        for(TextField feld : inputFields) {
            feld.setVisible(true);
        }

        /*Labels einblenden*/
        for (Label label : labels ) {
            label.setVisible(true);
        }
        System.out.println(name.getLayoutY());
        System.out.println(acronym.getLayoutY());
        /*nicht verwendete Labels ausblenden*/
        highscoreLabel.setVisible(false);
        currentScoreLabel.setVisible(false);
        soundLabel.setVisible(false);
        highscoreMenuLabel.setVisible(false);
        checkAcronymLabel.setVisible(false);
        checkNameLabel.setVisible(false);

        /*Click-Events*/
        startGameButton.setOnAction(event -> startGameButtonClick());
    }

    /*** alle
     * Hauptmenü wird ausgeblendet, Einstellungen folgen
     */
    public void settingsButtonClick() {
        /*Überschrift umbenennen*/
        headline.setText("EINSTELLUNGEN");

        /*nicht verwendete Buttons/ Labels ausblenden, gebrauchte einblenden*/
        startButton.setVisible(false);
        highscoresButton.setVisible(false);
        settingsButton.setVisible(false);
        menuButton.setVisible(true);
        soundSlider.setVisible(true);
        soundLabel.setVisible(true);

        background1.setVisible(true);
        background2.setVisible(true);

        background1.setOnAction(event ->  {
            /*Source als String*/
            String img = "file:src/main/resources/com/example/happy_bird/pics/Background0.png";

            /*Hintergrund zu Pane hinzufügen:*/
            Background background = new Background(formatingClass.backgroundFormating(img));
            pane.setBackground(background);
        });

        background2.setOnAction(event ->  {
            /*Source als String*/
            String img = "file:src/main/resources/com/example/happy_bird/pics/Background1.png";

            /*Hintergrund zu Pane hinzufügen:*/
            Background background = new Background(formatingClass.backgroundFormating(img));
            pane.setBackground(background);
        });
    }

    /*** alle
     * Hauptmenü wird ausgeblendet, Einstellungen folgen
     */
    public void settingsButtonPauseClick() {
        /*Überschrift umbenennen*/
        pauseMenuLabel.setText("EINSTELLUNGEN");

        /*alle Buttons ausblenden*/
        for(Button button : pauseButtons) {
            button.setVisible(false);
        }

        /*gebrauchte Buttons einblenden und anpassen*/
        backButtonPause.setVisible(true);
        backButtonPause.setLayoutY(300);

        /*soundSliderPause anpassen und einblenden*/
        soundSliderPause.setPrefSize(200, 5);
        soundSliderPause.setLayoutX(100);
        soundSliderPause.setLayoutY(150);
        soundSliderPause.setVisible(true);

        /*soundLabelPause einblenden*/
        soundLabelPause.setVisible(true);

        /*Click-Events*/
        backButtonPause.setOnAction(event -> {
            /*Überschrift umbenennen*/
            pauseMenuLabel.setText("PAUSE");

            /*alle Buttons einblenden*/
            for(Button button : pauseButtons) {
                button.setVisible(true);
            }

            /*nicht verwendete Buttons ausblenden*/
            backButtonPause.setVisible(false);
            soundSliderPause.setVisible(false);
            soundLabelPause.setVisible(false);
        });
    }

    /*** Pape
     * Hauptmenü wird ausgeblendet, Highscores folgen
     */
    public void highscoresButtonClick() {
        /*Überschrift umbenennen*/
        headline.setText("HIGHSCORES");
        /*Label für die Highscores einfügen und füllen*/
        highscoreMenuLabel.setLayoutX(275);
        highscoreMenuLabel.setLayoutY(225);
        highscoreMenuLabel.setPrefHeight(300);
        highscoreMenuLabel.setPrefSize(250, 250);
        highscoreMenuLabel.setVisible(true);

        String bestFiveHighscores = calculateHighscores();
        System.out.println(bestFiveHighscores);
        highscoreMenuLabel.setText(bestFiveHighscores);

        /*nicht verwendete Buttons ausblenden, verwendete einblenden*/
        startButton.setVisible(false);
        highscoresButton.setVisible(false);
        settingsButton.setVisible(false);
        menuButton.setVisible(true);
    }

    /*** alle
     * Nameneingabe, Einstellungen und Highscores werden ausgeblendet
     * Erneutes Anzeigen des Hauptmenüs
     */
    public void menuButtonClick() {
        /*Überschrift umbenennen*/
        headline.setText("HAPPY BIRD");

        /*nicht verwendete Buttons ausblenden, verwendete einblenden*/
        startButton.setVisible(true);
        highscoresButton.setVisible(true);
        settingsButton.setVisible(true);
        menuButton.setVisible(false);
        startGameButton.setVisible(false);
        highscoreMenuLabel.setVisible(false);

        background1.setVisible(false);
        background2.setVisible(false);

        /*soundSlider ausblenden*/
        soundSlider.setVisible(false);

        /*Textfelder ausblenden*/
        for(TextField feld : inputFields) {
            feld.setVisible(false);
        }

        /*alle Labels ausblenden*/
        for (Label label : labels ) {
            label.setVisible(false);
        }
    }

    /*** Pape
     * Startet Spiel nach Namenseingabe
     */

    public void startGameButtonClick() {
        if (correctName() == 0 && correctAcronym() == 0)
        {
            generateGameScreen();
            System.out.println(this.gameRunning);
            pauseButton.setDefaultButton(false);

            /*Klick auf den Pause-Button, um das Pause-Menü aufzurufen*/
            pauseButton.setOnAction(event -> {
                if (!menuScreenRunning) {
                    pauseButtonClick(this.gameRunning);
                    this.gameRunning = !this.gameRunning;
                }
            });



            /*  ESC-Taste zum Öffnen des Pause-Screens einbinden -
            *   Tasten W und S einbinden zum Verändern der Höhe des Vogels
            *   (W bewegt den Vogel hoch / S bewegt den Vogel runter)
            */
            birdPositionMovedBy = 0;
            scene.setOnKeyPressed(event -> {

            if (event.getCode() == KeyCode.W) {
                moveBirdUp();
            }
            if (event.getCode() == KeyCode.S) {
                moveBirdDown();
            }

            if (event.getCode() == KeyCode.ESCAPE && !menuScreenRunning) {
                pauseButtonClick(this.gameRunning);
                this.gameRunning = !this.gameRunning;
                }
            });


        } else {
            checkNameLabel.setVisible(false);
            checkAcronymLabel.setVisible(false);
            if (correctName() == 1) {
                checkNameLabel.setText("nicht erlaubte Zeichen!");
                checkNameLabel.setVisible(true);
            } else if (correctName() == 2) {
                checkNameLabel.setText("1. Buchstabe muss groß!");
                checkNameLabel.setVisible(true);
            } else if (correctName() == 3) {
                checkNameLabel.setText("Name nicht leer!");
                checkNameLabel.setVisible(true);
            }
            if (correctAcronym() == 1) {
                checkAcronymLabel.setText("nicht erlaubte Zeichen!");
                checkAcronymLabel.setVisible(true);
            } else if (correctAcronym() == 2) {
                checkAcronymLabel.setText("Länge 3-10 Zeichen!");
                checkAcronymLabel.setVisible(true);
            }
        }
    }

    /*** alle
     * Zurück zum Spiel aus dem PauseScreen heraus
     */
    public void continueButtonClick() {
        /*pauseButton einblenden*/
        pauseButton.setVisible(true);

        /*PauseScreen ausblenden*/
        pause.setVisible(false);

        /*Vom PauseScreen entfernen*/
        pause.getChildren().clear();
        pane.getChildren().remove(pause);

        /*Pausieren der Transitions/ Pipes*/
        for(Transition transition : transitions) {
            transition.play();
            //System.out.println(transition.toString());
        }

        /*Pausieren der Timeline, sodass keine neuen Pipes spawnen*/
        timeline.play();

        /*gameRunning auf false setzen, da sonst 2x Click auf Pause-Button bzw. ESC*/
        gameRunning = false;
    }

    /*** alle
     * alles vom pane entfernen, da als nächstes zum Hauptmenü
     */
    private void menuButtonPauseClick() {
        /*alles vom pauseScreen entfernen*/
        pause.getChildren().clear();
        pipesArrayList.clear();
        collectedPoints = 0;
        currentScoreLabel.setText("SCORE: " + collectedPoints);
        /*pause von pane entfernen*/
        pane.getChildren().clear();

        /*gameRunning auf false, da zurück zum Hauptmenü*/
        gameRunning = false;
    }

    /*** Alteköster
     * Ruft das Pause-Menü im Spiel auf oder blendet es wieder aus
     */
    public void pauseButtonClick(Boolean gameRuns) {
        formatingClass.pauseScreenFormating(pause, pauseMenuLabel, soundLabelPause);

        /*PauseScreen aufrufen, wenn das Spiel läuft, sonst wieder ausblenden*/
        if(!gameRuns) {
            pauseButton.setVisible(false);

            /*PauseScreen einblenden*/
            pause.setVisible(true);

            /*Buttons anpassen, zum pauseScreen hinzufügen und einblenden*/
            int yPosition = 100;
            for(Button button : pauseButtons) {
                button.setLayoutX(100);
                button.setLayoutY(yPosition);
                yPosition += 100;
                pause.getChildren().add(button);
                button.setVisible(true);
            }

            /*backButtonPause vorerst ausblenden und zu pause hinzufügen*/
            backButtonPause.setVisible(false);
            pause.getChildren().add(pauseMenuLabel);

            /*soundSliderPause vorerst ausblenden und zu pause hinzufügen*/
            soundSliderPause.setVisible(false);
            pause.getChildren().add(soundSliderPause);

            /*soundLabelPause vorerst ausblenden und zu pause hinzufügen*/
            soundLabelPause.setVisible(false);
            pause.getChildren().add(soundLabelPause);

            /*pause zu pane hinzufügen*/
            pane.getChildren().add(pause);

            /*ClickEvents*/
            continueButton.setOnAction(event -> continueButtonClick());

            menuButtonPause.setOnAction(event -> {
                menuButtonPauseClick();
                generateMenueScreen();
            });

            settingsButtonPause.setOnAction(event -> settingsButtonPauseClick());

            /*Pausieren der Transitions/ Pipes*/
            for(Transition transition : transitions) {
                transition.pause();
                System.out.println(transition.toString());
            }

            /*Pausieren der Timeline, sodass keine neuen Pipes spawnen*/
            timeline.pause();

        } else {
            /*pauseButton einblenden*/
            pauseButton.setVisible(true);

            /*PauseScreen ausblenden*/
            pause.setVisible(false);

            /*alles vom PauseScreen entfernen*/
            pause.getChildren().clear();

            /*pause von pane entfernen*/
            pane.getChildren().remove(pause);

            /*Wiederabspielen der Transitions/ Pipes*/
            for(Transition transition : transitions) {
                transition.play();
            }

            /*Wiederabspielen der Timeline, sodass neue Pipes spawnen*/
            timeline.play();
        }
    }

    /*** Pape
     * Erste Datenabfrage als Test - wird später gelöscht
     */
    public void dataQuery() {
        String dataquery = "SELECT * FROM happybirddb;";
        try (ResultSet rs = datenbank.st.executeQuery(dataquery)) {
            while (rs.next())
            {
                System.out.println(rs.getString(1) + " " + rs.getString(2)
                        + " " + rs.getString(3) + " " + rs.getString(4));
            }
        }
        catch (Exception e)
        {
            System.out.println("Falsche Abfrage");
        }
    }

    /*** Pape
     * getPlayerHighscore() berechnet den höchsten erreichten Wert des aktuellen Spielers
     * (nicht den gesamt höchsten Highscore)
     *
     * @return den Highscore des aktuellen Spielers
     */
    public int getPlayerHighscore() {
        int highscore = 0;
        String playeracronym = acronym.getText();
        String sql = "SELECT MAX(punkte) FROM happybirddb WHERE kuerzel = '" + playeracronym + "';";
        System.out.println(sql);
        try (ResultSet rs = datenbank.st.executeQuery(sql)) {
            while (rs.next())
            {
                highscore = rs.getInt(1);
            }
        }
        catch (Exception e)
        {
            System.out.println("Falsche Abfrage");
        }
        return highscore;
    }

    /*** Pape
     * calculateHighscores() gibt die Highscores aus ( die 5 höchsten Werte, die bis jetzt gespielt wurden )
     *
     * @return die 5 höchsten erreichten Scores
     */
    public String calculateHighscores() {
        String bestFiveHighscores = "PLAYER\t\tSCORE\n\n";
        int i = 0;
        String sql = "SELECT * FROM happybirddb ORDER BY punkte DESC LIMIT 5;";
        try (ResultSet rs = datenbank.st.executeQuery(sql)) {
            while (rs.next())
            {
                bestFiveHighscores += rs.getString(4) + "\t" + rs.getString(3)+"\n";
            }
        }
        catch (Exception e)
        {
            System.out.println("Falsche Abfrage");
        }
        return bestFiveHighscores;
    }

    /*** Pape
     * calculatePersonalHighscores() berechnet die 5 höchsten erreichten Scores des aktuellen Spielers
     *
     * @return die 5 höchsten erreichten Scores des aktuellen Spielers
     */
    public String calculatePersonalHighscores() {
        String bestFiveHighscores = "PLAYER\t\tSCORE\n\n";
        String currentPlayer = acronym.getText();
        int i = 0;
        String sql = "SELECT * FROM happybirddb WHERE kuerzel = '" + currentPlayer + "' ORDER BY punkte DESC LIMIT 5;";
        System.out.println(sql);
        try (ResultSet rs = datenbank.st.executeQuery(sql)) {
            while (rs.next())
            {
                bestFiveHighscores += rs.getString(4) + "\t" + rs.getString(3)+"\n";
            }
        }
        catch (Exception e)
        {
            System.out.println("Falsche Abfrage");
        }
        return bestFiveHighscores;
    }

    /*** Pape
     * Fügt die erreichte Punktzahl des Spielers für den Spieler mit seinem Namen und Kürzel in die Datenbank ein
     *
     */
    public void writeIntoDatabase() {
        String playername = name.getText();
        String playeracronym = acronym.getText();
        /*String sql = "INSERT INTO happybirddb(name, kuerzel, punkte) VALUES ('" + playername + "', '" + points +
                "', '" + playeracronym + "');";*/
        String sql = "INSERT INTO happybirddb (name, kuerzel, punkte) VALUES (?, ?, ?);";
        try (PreparedStatement ps = datenbank.con.prepareStatement(sql)) {
            ps.setString(1, playername);
            ps.setString(2, playeracronym);
            ps.setInt(3, collectedPoints / 2);
            System.out.println(ps);
            ps.execute();
        }
        catch (Exception e)
        {
            System.out.println("Insert fehlschlagen");
        }
    }

    /*** Pape
     * Überprüft, ob der eingegebene Name den Vorgaben entspricht
     * (Erlaubte Zeichen: Groß- und Kleinbuchstaben, Umlaute und Leerzeichen
     *
     * @return  0, wenn ja,
     * sonst:   1, wenn nicht erlaubte Zeichen verwendet
     *          2, wenn der 1. Buchstabe kleingeschrieben ist
     *          3, wenn der Name leer ist
     */
    public int correctName() {
        String nametext = name.getText();
        if (!nametext.matches("[a-zA-ZÄÖÜäöüß ]*"))
        {
            System.out.println("Fehler Schreibweise Name - nicht erlaubte Zeichen");
            return 1;
        }
        if (nametext.length() > 0)
        {
            if (nametext.charAt(0) < 'A' || nametext.charAt(0) > 'Z')
            {
                System.out.println("Fehler Schreibweise Name - 1. Buchstabe muss großgeschrieben werden");
                return 2;
            }
        }
        else
        {
            System.out.println("Name darf nicht leer sein");
            return 3;
        }
        return 0;
    }

    /*** Pape
     * Überprüft, ob das eingegebene Akronym den Vorgaben entspricht
     * ( >= 3 Zeichen, <= 12 Zeichen, Groß- und Kleinbuchstaben, Zahlen 0-9 -- keine Sonderzeichen)
     * @return  0, wenn ja,
     * sonst:   1, wenn die Länge nicht korrekt ist
     *          2, wenn nicht erlaubte Zeichen verwendet werden
     */
    public int correctAcronym() {
        String acronymtext = acronym.getText();
        System.out.println(acronymtext.length());
        System.out.println(acronymtext);
        if (!acronymtext.matches("[A-Za-z0-9]*"))
        {
            System.out.println("Fehler Schreibweise Kürzel - nur Buchstaben und Zahlen erlaubt");
            return 1;
        }
        if (acronymtext.length() < 3 || acronymtext.length() > 10)
        {
            System.out.println("Fehler Länge Kürzel (3-10 Zeichen)");
            return 2;
        }
        return 0;
    }

    /*** Pape, Bickmann, Ekmen
     * public void generateEndScreen() generiert den Endscreen - sobald das Spiel beendet ist
     * (man verloren hat). Es werden die Punkte des Spielers angezeigt, und es bestehen die Möglichkeiten,
     *      das Spiel neu zu starten
     *      das zum Hauptmenü zurückzukehren
     *      sich seine persänlichen Highscores anzeigen zu lassen
     */
    public void generateEndScreen() {
        formatingClass.endScreenFormating(endScreen, endScreenHeadline, currentScoreEndscreenLabel);
        /*Name und Highscores ausblenden, Pause-Button ausblenden*/
        nameLabel.setVisible(false);
        highscoreLabel.setVisible(false);
        pauseButton.setVisible(false);
        currentScoreLabel.setVisible(false);

        endScreen.getChildren().add(endScreenHeadline);
        endScreenHeadline.setVisible(true);

        endScreen.getChildren().add(currentScoreEndscreenLabel);
        currentScoreEndscreenLabel.setText("YOUR SCORE: " + collectedPoints / 2);
        currentScoreEndscreenLabel.setVisible(true);

        /* Buttons einfügen */
        int yPosition = 200;
        for (Button button : endscreenButtons) {
            button.setLayoutX(100);
            button.setLayoutY(yPosition);
            yPosition += 100;
            endScreen.getChildren().add(button);
            button.setVisible(true);
        }
        pane.getChildren().add(endScreen);
        backEndscreenButton.setVisible(false);
        /* Click-Events für die Buttons */
        backMenuButton.setOnAction(event -> backMenuButtonClick());
        personalHighscoresButton.setOnAction(event -> personalHighscoresButtonClick());
        restartGameButton.setOnAction(event -> restartGameButtonClick());
    }

    /*** Pape, Bickmann, Ekmen
     * die Funktion restartGameButtonClick() startet das Spiel neu
     */
    private void restartGameButtonClick() {
        pane.getChildren().remove(endScreen);
        pane.getChildren().remove(happyBird);
        for (Rectangle pipe : pipesArrayList) {
            pane.getChildren().remove(pipe);
        }
        pipesArrayList.clear();
        collectedPoints = 0;
        currentScoreLabel.setText("SCORE: " + collectedPoints);
        endScreenOpened = false;
        openEndScreen = false;
        endScreen.getChildren().clear();
        startGameButtonClick();
    }

    /*** Pape
     * personalHighscoresButtonClick() zeigt bei Drücken des Highscore-Buttons im Endscreen
     * die persänlichen besten 5 Scores an
     */
    private void personalHighscoresButtonClick() {
        /* alle Buttons ausblenden */
        System.out.println("Highscore-Button");
        for(Button button : endscreenButtons) {
            button.setVisible(false);
        }
        /* Back-Button einblenden */
        backEndscreenButton.setLayoutY(425);
        backEndscreenButton.setVisible(true);

        /* Überschrift ändern */
        endScreenHeadline.setText("YOUR SCORES");

        /* Highscore ausblenden */
        currentScoreEndscreenLabel.setVisible(false);

        /* Highscore-Label (Hintergrund) formatieren und einfügen */
        highscoreMenuLabel.setLayoutX(75);
        highscoreMenuLabel.setLayoutY(100);
        highscoreMenuLabel.setPrefSize(250, 300);
        endScreen.getChildren().add(highscoreMenuLabel);
        highscoreMenuLabel.setVisible(true);

        /* Highscores des Spielers einfügen */
        String personalBestScores = calculatePersonalHighscores();
        highscoreMenuLabel.setText(personalBestScores);

        /* Zurück-Funktion in den Endscreen */
        backEndscreenButton.setOnAction(event -> {
            endScreenHeadline.setText("GAME OVER");

            for(Button button : endscreenButtons) {
                button.setVisible(true);
            }
            currentScoreEndscreenLabel.setVisible(true);
            highscoreMenuLabel.setVisible(false);
            backEndscreenButton.setVisible(false);
            endScreen.getChildren().remove(highscoreMenuLabel);
        });
    }

    /*** Pape, Bickmann, Ekmen
     * backMenuButtonClick() ruft aus dem Endscreen das Hauptmenü auf
     */
    private void backMenuButtonClick() {
        pane.getChildren().remove(endScreen);
        pane.getChildren().clear();
        for (Rectangle pipe : pipesArrayList) {
            pane.getChildren().remove(pipe);
        }
        pipesArrayList.clear();
        collectedPoints = 0;
        currentScoreLabel.setText("SCORE: " + collectedPoints);
        endScreenOpened = false;
        openEndScreen = false;
        endScreen.getChildren().clear();
        generateMenueScreen();
    }

    /*** Bickmann
     * Aufstieg dauert immer länger
     */
    private void moveBirdUp() {
        velocity = (float) -4.5;
        var pos = velocity += gravity;
        birdPositionMovedBy += pos;
        happyBird.setLayoutY(birdPositionMovedBy);
    }

    /*** Bickmann
     * Fall geht schneller
     */
    private void moveBirdDown() {
        var pos = velocity -= gravity;
        birdPositionMovedBy -= pos;
        happyBird.setLayoutY(birdPositionMovedBy);
    }
}