package de.subway_surfers.vpr_app;

import Logik.Account;
import Logik.ElternAccount;
import Logik.Kind;
import Logik.MitarbeiterAccount;
import RestAPISchnittstelle.RestApiClient;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.Background;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.Random;

public class AccounterstellungMitarbeiter {

	private @FXML TextField accountname;
	private @FXML TextField email;
	private @FXML Label status;
	private @FXML Label einmalpw;
	private @FXML HBox kindanzeige;
	private @FXML GridPane kindDaten;
	private @FXML RadioButton typMitarbeiter;
	private @FXML RadioButton typEltern;
	private       ToggleGroup accountTyp;

	private ArrayList<Kind> kinder;

	/**
	 * Initialisiert die Accounterstellungsmaske
	 * @author Sven Alteköster
	 */
	public void initialize() {
		//Die Radiobuttons zum auswählen eines Accountypes werden einer ToggleGroup hinzugefügt
		accountTyp = new ToggleGroup();
		accountTyp.getToggles().add(typEltern);
		accountTyp.getToggles().add(typMitarbeiter);

		einmalpw.setText(einmalPwGenerieren());

		//kinder wird initialisiert
		kinder = new ArrayList<>();
	}

	/**
	 * Hauptmenü wird angezeigt
	 *
	 * @param actionEvent
	 * @author Sven Alteköster
	 */
	public void onZurueck(ActionEvent actionEvent) {
		VerwaltungApplication.sceneWechseln("hauptmenue_mitarbeiter-view.fxml");
	}

	/**
	 * Der nutzer wird abgemeldet
	 * @param actionEvent
	 * @author Sven Alteköster
	 */
	public void onAbmelden(ActionEvent actionEvent) {
		VerwaltungApplication.abmelden();
	}

	/**
	 * Die Felder zum Erstellen von Kindern werden gelöscht
	 * @param actionEvent
	 * @author Sven Alteköster
	 */
	public void onTypMitarbeiter(ActionEvent actionEvent) {
		kindDaten.getChildren().clear();
	}

	/**
	 * Einfügen der Eingabefelder für Kinder, wenn der Eltern-Radiobutton ausgewählt wird
	 * @param actionEvent
	 * @author Sven Alteköster
	 */
	public void onTypEltern(ActionEvent actionEvent) {
		//Einfügen der Eingabefelder für Kinder

		//Einfügen der Überschrift
		Label ueberschrift = new Label();
		ueberschrift.setText("Daten des Kindes:");
		kindDaten.addRow(0);
		kindDaten.addColumn(0);
		kindDaten.addRow(1);
		kindDaten.add(ueberschrift,0,0);

		//Einfügen der Eingabe für den Vornamen eines Kindes
		kindDaten.addRow(1);
		Label vname = new Label("Vorname:");
		kindDaten.add(vname, 0, 1);
		TextField vnameEingabe = new TextField();
		kindDaten.add(vnameEingabe, 1, 1);

		//Einfügen der Eingabe für den Nachnamen eines Kindes
		kindDaten.addRow(2);
		Label nname = new Label("Nachname:");
		kindDaten.add(nname, 0, 2);
		TextField nnameEingabe = new TextField();
		kindDaten.add(nnameEingabe, 1, 2);

		//Einfügen der Eingabe für den Geburtstag eines Kindes
		kindDaten.addRow(3);
		Label geburtstag = new Label("Geburtstag: ");
		kindDaten.add(geburtstag, 0, 3);
		DatePicker geburtstagEingabe = new DatePicker();
		geburtstagEingabe.setEditable(false);
		kindDaten.add(geburtstagEingabe, 1, 3);

		//Einfügen des bestätigen Buttons
		kindDaten.addRow(4);
		Button hinzufuegen = new Button("hinzufügen");
		kindDaten.add(hinzufuegen, 1, 4);

		if (kindDaten.getRowCount() < 5) {
			kindDaten.addRow(5);
		}

		//wird der Button zum hinzufügen eines Kindes geclickt wird dieses Event ausgelöst
		hinzufuegen.setOnAction(e -> {
			Button neues = new Button(vnameEingabe.getText());

			boolean vnameGueltig = false;
			boolean gebGueltig = false;
			boolean nnameGueltig = false;

			//Wenn alle Eingabefelder für Kinder ausgefüllt sind ist die Eingabe gültig
			if (!vnameEingabe.getText().equals("")) {
				vnameGueltig = true;
			}

			if (!nnameEingabe.getText().equals("")) {
				nnameGueltig = true;
			}

			if (!geburtstagEingabe.getEditor().getText().equals("")) {
				gebGueltig = true;
			}

			if (vnameGueltig && gebGueltig && nnameGueltig) {
				Kind kind = new Kind(nnameEingabe.getText(), vnameEingabe.getText(), 0);
				kinder.add(kind);
				kindanzeige.getChildren().add(neues);
				//Wird auf ein Kind in der Anzeige geclickt, wird es aus der Liste entfernt.
				neues.setOnAction(a -> {
					((HBox) neues.getParent()).getChildren().remove(neues);
					kinder.remove(kind);
				});
				//Die Eingabefelder werden zurückgesetzt
				vnameEingabe.setText("");
				nnameEingabe.setText("");
				geburtstagEingabe.getEditor().setText("");
			}
		});
	}

	/**
	 * Generiert ein zufälliges Passwort bestehend aus Buchstaben zwischen A und Z
	 * @return ein Passwort der länge pwLaenge
	 * @author Sven Alteköster
	 */
	private String einmalPwGenerieren() {
		final int pwLaenge = 8;
		String pw = "";
		Random zufall = new Random();
		for (int i = 0; i < pwLaenge; i++) {
			pw += (char)zufall.nextInt('A', 'Z' + 1);
		}
		return pw;
	}

	/**
	 * Prüft, ob in allen Textfeldern für die Eltern Text steht.
	 * @return true, wenn kein Feld leer ist
	 * @author Sven Alteköster
	 */
	private boolean eingabenGueltig() {
		return !accountname.getText().equals("") && !email.getText().equals("") && (typEltern.isSelected() || typMitarbeiter.isSelected());
	}

	/**
	 * Speichert die Eingegebenen Daten in der Datenbank, wenn diese noch nicht vorhanden sind
	 * @param actionEvent
	 * @author Sven Alteköster
	 */
	public void onSpeichern(ActionEvent actionEvent) {
		if (eingabenGueltig()) {

			//speichert das aktuelle Passwort zwischen
			String passwort = einmalpw.getText();

			//generiert ein neues Einmalpasswort und zeigt es an
			einmalpw.setText(einmalPwGenerieren());

			//Schnittstelle zur RestAPI
			RestApiClient api = new RestApiClient();

			Gson gson = new Gson();

			//id, die das Elternobjekt bekommt, dass im laufe der Methode erstellt wird
			String[] accName = {String.format("name=%s", accountname.getText())};

			String json = api.get("Benutzer", accName);
			int id = api.nextId("Benutzer");
			boolean kontoVorhanden = false;
			if (!json.equals("false")) {
				kontoVorhanden = true;
				id = gson.fromJson(json, Account.class).getId();
			}

			//Erstellen des neuen Accounts
			Account neuer;
			//Handelt es sich um einen Elternaccount, werden alle Eingegebenen Kinder erstellt.
			if (typEltern.isSelected()) {
				neuer = new ElternAccount(passwort, accountname.getText(), email.getText());
				//Kinder dem neuen Account hinzufügen
				for (Kind k : kinder) {
					((ElternAccount)neuer).getKinder().add(k);
				}
			}
			else if (typMitarbeiter.isSelected()) {
				neuer = new MitarbeiterAccount(passwort, accountname.getText(), email.getText());
			}
			//Ist kein Radio Button ausgewählt, wird hier abgebrochen
			else {
				return;
			}

			//Die Liste, zum Speichern der gespeicherten Liste wird zurückgesetzt, da die Kinder jetzt im Elternobjekt gespeichert werden
			kinder.clear();

			//Das Elternelement wird in der DB gespeichert, wenn es keinen gleichnamigen Account gibt.
			if (!kontoVorhanden) {
				api.post("Benutzer", gson.toJson(neuer));
			}


			//handelt es sich um einen Elternaccount, werden alle Kind-Objekte in der DB gespeichert
			if (neuer instanceof ElternAccount) {
				for (Kind k : ((ElternAccount)neuer).getKinder()) {
					//setzen des Fremdschlüssels bid
					k.setBid(id);
					api.post("Kind", gson.toJson(k));
				}
			}
			status.setText("Daten Erfolgreich gespeichert");
		}
		else {
			status.setText("Accounterstellung Fehlgeschlagen");
		}

		kindanzeige.getChildren().clear();
		kinder.clear();
	}

	/**
	 * Lädt alle zugehörigen Daten aus der Datenbank, die mit dem eingegebenen Benutzernamen übereinstimmen
	 * @param actionEvent
	 * @author Sven Alteköster
	 */
	public void onLaden(ActionEvent actionEvent) {
		kindanzeige.getChildren().clear();
		kinder.clear();

		Gson gson = new Gson();
		RestApiClient api = new RestApiClient();

		String[] params =  {String.format("name=%s", accountname.getText())};
		String jsonAcc = api.get("Benutzer", params);

		Account acc;
		//Handelt es sich um einen Mitarbeiter, wird dieser ausgewählt un die zugehörigen Felder werden ausgefüllt
		if (jsonAcc.contains("\"rid\":\"0\"")) {
			acc = gson.fromJson(jsonAcc, MitarbeiterAccount.class);

			accountTyp.selectToggle(typMitarbeiter);
		}
		//Handelt es sich um einen Elternaccount werden die Felder ausgefüllt und alle Kinder geladen
		else if (jsonAcc.contains("\"rid\":\"1\"")) {
			acc = gson.fromJson(jsonAcc, ElternAccount.class);

			accountTyp.selectToggle(typEltern);
			onTypEltern(new ActionEvent());

			kindDaten.addRow(5);

			String jsonString = api.get("Kind", acc.getId());
			JsonElement je = JsonParser.parseString(jsonString);
			JsonArray ja = je.getAsJsonArray();

			//Alle Kinder werden als clickbarer Button eingefügt
			for (JsonElement str : ja) {
				Kind kind = gson.fromJson(str, Kind.class);

				Button btn = new Button();
				btn.setText(kind.getVorname());

				kindanzeige.getChildren().add(btn);

				//Wird der Button gecklickt, wird das Kind gelöscht
				btn.setOnAction(a -> {
					api.delete("Kind", kind.getId());
					//Der geclickte Button wird entfernt
					((HBox) btn.getParent()).getChildren().remove(btn);
				});
			}

		}
		//Wird der Account nicht gefunden, wird abgebrochen
		else {
			status.setText("Account nicht gefunden");
			return;
		}
		email.setText(acc.getEmail());
	}
}
