package Übungen.BlackJack;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.Scanner;

// Modell
public class BlackJack {
	private String spielerName;
	private int guthaben;
	private int punkte;
	private int speichereEinsatz;
	private boolean hitspiele;

	public BlackJack(String spielerName, int guthaben) {
		this.spielerName = spielerName;
		this.guthaben = guthaben;
		this.punkte = 0;
		this.speichereEinsatz = 0;
		this.hitspiele = false;
	}

	public int getSpeichereEinsatz() {
		return speichereEinsatz;
	}

	public void setSpeichereEinsatz(int speichereEinsatz) {
		this.speichereEinsatz = speichereEinsatz;
	}

	public String getSpielerName() {
		return spielerName;
	}

	public void setSpielerName(String spielerName) {
		this.spielerName = spielerName;
	}

	public int getGuthaben() {
		return guthaben;
	}

	public void addGuthaben(int betrag) {
		this.guthaben += betrag;
	}

	public void subtrahiereGuthaben(int betrag) {
		this.guthaben -= betrag;
	}

	public int getPunkte() {
		return punkte;
	}

	public void addPunkte(int punkte) {
		this.punkte += punkte;
	}

	public boolean isHitspiele() {
		return hitspiele;
	}

	public void setHitspiele(boolean hitspiele) {
		this.hitspiele = hitspiele;
	}

	@Override
	public String toString() {
		return "Spieler [Name=" + spielerName + ", Guthaben=" + guthaben + "€]";
	}
}

// Die GUI klasse oder View
class BlackJackView {
	private Scanner scanner;

	public BlackJackView() {
		scanner = new Scanner(System.in);
	}

	public void zeigeSpielerDetails(BlackJack spieler) {
		System.out.println(spieler.getSpielerName() + " hat " + spieler.getGuthaben() + "€ und " + spieler.getPunkte()
				+ " Punkte.");
	}

	public void zeigeNachricht(String nachricht) {
		System.out.println(nachricht);
	}

	public int frageEinsatz() {
		System.out.println("Wähle einen Einsatz von: [5€, 10€, 25€, 100€]");
		return scanner.nextInt();
	}

	public String frageObGuthabenAufladen() {
		System.out.println("Du hast nicht genug Guthaben. Möchtest du Guthaben aufladen? Ja/Nein");
		return scanner.next();
	}

	public int frageGuthabenBetrag() {
		System.out.println("Wie viel möchtest du aufladen?");
		return scanner.nextInt();
	}

	public String frageObHitOderStand() {
		System.out.println("Du hast nicht genug Guthaben. Möchtest du Guthaben aufladen? Ja/Nein");
		return scanner.next();
	}

	public void schließeScanner() {
		scanner.close();
	}
}

// Controller verwaltung das Spielabluaf
class Spiel {

	private BlackJack spieler1;
	private BlackJack spieler2;
	private ArrayList<Integer> kartendeck;
	private Random random;
	private ArrayList<Integer> erlaubteEinsätze;
	private BlackJackView view;

	public Spiel(BlackJack spieler1, BlackJack spieler2, BlackJackView view) {
		this.spieler1 = spieler1;
		this.spieler2 = spieler2;
		this.view = view;
		this.random = new Random();
		this.erlaubteEinsätze = new ArrayList<>();
		kartendeck = new ArrayList<>();
		initialisiereKartendeck();
	}

	public void initialisiereKartendeck() {
		for (int i = 1; i <= 11; i++) {
			kartendeck.add(i);
		}
		Collections.shuffle(kartendeck);
	}

	public ArrayList<Integer> getKartendeck() {
		return kartendeck;
	}

	public boolean guthabenAufladen(BlackJack spieler) {
		String antwort = view.frageObGuthabenAufladen();
		if (antwort.equalsIgnoreCase("ja")) {
			int betrag = view.frageGuthabenBetrag();
			if (betrag > 0) {
				spieler.addGuthaben(betrag);
				view.zeigeNachricht("Dein neues Guthaben: " + spieler.getGuthaben() + "€");
				return true;
			}
		}
		return false;
	}

	public boolean einsatzBestimmen(BlackJack spieler) {
		erlaubteEinsätze.add(5);
		erlaubteEinsätze.add(10);
		erlaubteEinsätze.add(25);
		erlaubteEinsätze.add(100);

		boolean einsatzAkzeptiert = false;
		view.zeigeNachricht(
				"Hallo " + spieler.getSpielerName() + ", dein aktuelles Guthaben: " + spieler.getGuthaben() + "€");
		while (!einsatzAkzeptiert) {
			if (spieler.getGuthaben() < 5) {
				if (guthabenAufladen(spieler)) {
					continue;
				} else {
					return false;
				}
			}

			int einsatz = view.frageEinsatz();
			if (!erlaubteEinsätze.contains(einsatz)) {
				view.zeigeNachricht("Falsche Eingabe. Bitte versuche es erneut.");
				continue;
			}

			if (einsatz > spieler.getGuthaben()) {
				if (guthabenAufladen(spieler)) {
					continue;
				} else {
					return false;
				}
			}

			if (erlaubteEinsätze.contains(einsatz)) {
				spieler.setSpeichereEinsatz(einsatz);
				spieler.subtrahiereGuthaben(einsatz);
				view.zeigeNachricht("Neues Guthaben: " + spieler.getGuthaben() + "€");
				einsatzAkzeptiert = true;
			}
		}
		return einsatzAkzeptiert;
	}

	public void zweiKartenZiehen() {
		int punkte1 = zieheZweiKarten(spieler1);
		view.zeigeNachricht(spieler1.getSpielerName() + " hat " + punkte1 + " Punkte.");

		int punkte2 = zieheZweiKarten(spieler2);
		view.zeigeNachricht(spieler2.getSpielerName() + " hat " + punkte2 + " Punkte.");
	}

	private int zieheZweiKarten(BlackJack spieler) {
		int ersteKarte = kartendeck.get(random.nextInt(kartendeck.size()));
		int zweiteKarte = kartendeck.get(random.nextInt(kartendeck.size()));
		int summe = ersteKarte + zweiteKarte;
		spieler.addPunkte(summe);
		return summe;
	}

	public void gewinnerPrüfen(BlackJack spieler1, BlackJack spieler2) {
		if (spieler1.getPunkte() < 22 && (spieler1.getPunkte() > spieler2.getPunkte() || spieler2.getPunkte() > 21)) {
			int gewinn = spieler1.getSpeichereEinsatz() * 2;
			spieler1.addGuthaben(gewinn);
			view.zeigeNachricht(
					spieler1.getSpielerName() + " hat gewonnen! Neues Guthaben: " + spieler1.getGuthaben() + "€");
		} else if (spieler2.getPunkte() < 22
				&& (spieler2.getPunkte() > spieler1.getPunkte() || spieler1.getPunkte() > 21)) {
			int gewinn = spieler2.getSpeichereEinsatz() * 2;
			spieler2.addGuthaben(gewinn);
			view.zeigeNachricht(
					spieler2.getSpielerName() + " hat gewonnen! Neues Guthaben: " + spieler2.getGuthaben() + "€");
		} else {
			view.zeigeNachricht("Unentschieden!");
		}
	}

	public void bestimmeSpieabluaf(BlackJack spieler) {
		view.zeigeNachricht("------------------------------------------");
		view.zeigeNachricht("Willkommen im Blackjack-Spiel:");
		zweiKartenZiehen();
		spieler.setHitspiele(true);
		while (spieler.isHitspiele()) {
			if (spieler.getPunkte() >= 21)
				spieler.setHitspiele(false);

			if (spieler.isHitspiele()) {
				view.zeigeNachricht(spieler.getSpielerName() + " : Möchten Sie hit oder stand? Aktuelle Hand: "
						+ spieler.getPunkte());
				String auswahl = view.frageObHitOderStand();

				if (auswahl.equalsIgnoreCase("hit")) {
					eineKarteZiehen(spieler);
					spielerPunkteAnzeigen(spieler);
				} else if (auswahl.equalsIgnoreCase("stand")) {
					spieler.setHitspiele(false);
					spielerPunkteAnzeigen(spieler);
				} else {
					view.zeigeNachricht("Falsche Eingabe: Bitte geben Sie entweder 'hit' oder 'stand' ein.");
					continue;
				}
			}
		}
	}

	public void eineKarteZiehen(BlackJack spieler) {
		int karte = kartendeck.get(random.nextInt(kartendeck.size()));
		spieler.addPunkte(karte);
		view.zeigeNachricht(spieler.getSpielerName() + " hat " + spieler.getPunkte() + " Punkte.");
	}

	public void spielerPunkteAnzeigen(BlackJack spieler) {
		view.zeigeNachricht(spieler.getSpielerName() + " hat " + spieler.getPunkte() + " Punkte.");
	}

}
