package de.jaujau.spiellogik;

import java.util.Random;

import de.jaujau.daten.Audio;
import de.jaujau.daten.Farbe;
import de.jaujau.daten.Kartensatz;
import de.jaujau.daten.Spieler;
import de.jaujau.daten.Wert;
import de.jaujau.gui.Dashboard_GUI;



/**
 * Diese Klasse organisiert den Spielablauf
 * Diese Klasse beinhaltet Methoden um Spielzüge auszuführen, um Kontrollen durchzuführen und um zwischen Spieler und Computer zu wechseln
 * @author Fabian Keller 
 */
public class Spiel {

	private Spieler amZug;
	private Wert gelegterWert;
	private Audio audio;
	private Kartensatz kartensatz;
	private Spielzug spielzug;
	private Computer_gegner computerGegner;
	private boolean aussetzen;
	private boolean zwei_ziehen;
	private int kartenZiehen;
	private Dashboard_GUI dashboard;
	private boolean spielGewonnen;
	private boolean debug = false;
	
	public Spiel(Dashboard_GUI dashboard_gui) {
		audio = new Audio();
		kartensatz = new Kartensatz();
		computerGegner = new Computer_gegner(kartensatz);
		spielzug = new Spielzug(kartensatz);
		dashboard = dashboard_gui;
		spielGewonnen = false;
	}
	
	public boolean getAussetzen() {
		return aussetzen;
	}


	public boolean getZwei_ziehen() {
		return zwei_ziehen;
	}

	
	public Kartensatz getKartensatz() {
		return kartensatz;
	}


	public Spieler getamZug() {
		return amZug;		
	}
	
	
	/**
	 * Initialisiert ein Spiel
	 * Handelt den Start aus und führt, falls nötig, den ersten Spielzug aus
	 * @param dashboard
	 */
	public void spiel(Dashboard_GUI dashboard) {
		if(debug) System.out.println("\nSPIEL Spiel gestartet.");
		Random zufallszahl = new Random();
		int zahl = zufallszahl.nextInt(2);
		if(zahl == 1) { //Starter durch zufall bestimmen
			amZug = Spieler.SPIELER;
			if(debug) System.out.println("SPIEL Spieler startet");
		}
		else { 
			amZug = Spieler.COMPUTER;
			if(debug) System.out.println("SPIEL Computer startet");
		}
		for(int i = 0; i < 7; i++) { //Jeder bekommt 7 Karten
			kartensatz.ziehen(Spieler.COMPUTER);
			kartensatz.ziehen(Spieler.SPIELER);
		}
		if(debug) System.out.println("SPIEL Kartenhand von COMPUTER: " + kartensatz.getHand(Spieler.COMPUTER));
		if(debug) System.out.println("SPIEL Kartenhand von SPIELER:  " + kartensatz.getHand(Spieler.SPIELER));
		effekteSetzen(); //effekte für den Start setzen
		if(amZug == Spieler.COMPUTER) { //falls der PC startet, findet hier der erste Zug statt
			int computerZug = computerGegner.cpu_Zug(zwei_ziehen, aussetzen, kartensatz);
			if(debug) System.out.println("\nSPIEL Computerauswahl: " + computerZug);
			switch(computerZug) {
			case -2: //aussetzen
				aussetzen = false;
				alternieren(dashboard);
				break;
			case -1: //Karte ziehen
				karteZiehen();
				break;
			default: //Karte legen
				karteLegen(computerZug);
				break;
			}	
		}
		else if(amZug == Spieler.SPIELER) {//falls der Spieler startet wird noch der Aussetzen-Button eingeblendet 
			if(aussetzen) dashboard.showaussetzen(true);
		}
		return;			
	}
	
	
	/**
	 * Organisiert den Spielablauf nach jedem gültigen Zug, wechselt zwischen Spieler und Computer
	 * @param dashboard
	 */
	private void alternieren(Dashboard_GUI dashboard) {
		if(spielGewonnen) return;
		if(amZug == Spieler.SPIELER) { //CPU Zug findet statt
			amZug = Spieler.COMPUTER;
			dashboard.aktualisiereGUI();
			if(debug) System.out.println("\nSPIEL Computer am Zug");
			int computerZug = computerGegner.cpu_Zug(zwei_ziehen, aussetzen, kartensatz);
			if(debug) System.out.println("SPIEL Computerauswahl: " + computerZug);
			switch(computerZug) {
			case -2: 
				aussetzen = false;
				alternieren(dashboard);
				break;
			case -1:
				karteZiehen();
				break;
			default:
				karteLegen(computerZug);
				break;
			}	
			
		}
		else { //Spieler Zug findet statt
			amZug = Spieler.SPIELER;
			dashboard.aktualisiereGUI();
			if(debug) System.out.println("\nSPIEL Spieler am Zug");
			if(aussetzen) { //falls aussetzen aktiv, wird die Möglichkeit über den Button aktiviert
				if(debug) 	System.out.println("\nSPIEL Aussetzen möglich");
				dashboard.showaussetzen(true);	
				dashboard.aktualisiereGUI();
			}
		}
	}
	
	
	/**
	 * Wird aufgerufen wenn das Spiel entschieden wurde, führt zum Spielende
	 * @param spieler Spieler, welcher gewonnen hat 
	 */
	private void gewinn(Spieler spieler) {
		if(debug) System.out.println("HERZLICHEN GLÜCKWUNSCH " + spieler + ". DU HAST GEWONNEN");
		dashboard.gewonnen(spieler);
		spielGewonnen = true;
	}
	
	
	/**
	 * Bietet für den Spieler die Möglichkeit auszusetzen
	 */
	public void aussetzen() {
		if(spielGewonnen) return;
		aussetzen = false;
		alternieren(dashboard);
	}
	
	/**
	   * falls eine Karte gelegt werden kann, wird diese für den Teilnehmer gelegt 
	   * @param       	kartenindex
	   */
	public void karteLegen(int kartenindex) {
		if(spielGewonnen) return;
		if(debug) System.out.println("SPIEL Versuche Karte " + kartenindex + " zu legen");
		if (spielzug.pruefeZug(kartenindex, zwei_ziehen, aussetzen, kartensatz)) { //gewählte Karte kann gelegt werden - Zug kann stattfinden | sonst nichts
			if(debug) System.out.println("SPIEL pruefeZug positiv");
			if(debug) System.out.println("SPIEL Lege Karte " + kartenindex);
			kartensatz.ablegen(kartenindex); //karte ablegen
			if(kartensatz.getHand(amZug).size() == 1) { //Teilnehmer hat nur noch eine Karte
				audio.spieleJau();
			}
			if(kartensatz.getHand(amZug).isEmpty()) { //Teilnehmer hat gewonnen
				audio.spieleJauJau();
				gewinn(amZug); //amZug hat gewonnen 
				return;
			}
			if(debug) 	System.out.println("SPIEL Kartenhand von COMPUTER: " + kartensatz.getHand(Spieler.COMPUTER));
			if(debug) System.out.println("SPIEL Kartenhand von SPIELER:  " + kartensatz.getHand(Spieler.SPIELER));
			effekteSetzen(); //effekte neu setzen
			if(kartensatz.getKarte(kartenindex).getWERT() == Wert.ACHT) { //Sonderfall: wiederholtes aussetzen Spieler
				if(amZug == Spieler.SPIELER)		dashboard.showaussetzen(false);
			}
			if(kartensatz.getKarte(kartenindex).getWERT() == Wert.BUBE) { //Sonderfall: Wünscher wurde gelegt Spieler
				if(amZug == Spieler.COMPUTER)	alternieren(dashboard);
			}
			else {
				alternieren(dashboard); //weiter ohne Sonderfall
			}
		}		
	}
	
	
	/**
	   * falls eine oder mehrere Karten gezogen werden können, wird dies für den Teilnehmer ausgeführt 
	   */
	public void karteZiehen(){
		if(spielGewonnen) return;
		if(!aussetzen) {
			if(zwei_ziehen) { //mehrere ziehen
				if(debug) System.out.println("\nSPIEL " + kartenZiehen + " Karten gezogen");
				for(int i = 0; i < kartenZiehen; i++) {	
					kartensatz.ziehen(amZug);
				}
				kartenZiehen = 0;
				zwei_ziehen = false;	
			}
			else { //Normales (1) ziehen
				kartensatz.ziehen(amZug);
				if(debug) System.out.println("\nSPIEL 1 Karte gezogen");
			}
			alternieren(dashboard);
		}
		else { //ziehen nicht möglich - nichts passiert
			return;
		}
	}
	
	
	/**
	 * Setzt die Wunschfarbe für den Spieler
	 * @param farbe
	 */
	public void wuenscher(Farbe farbe) {
		if(debug) System.out.println("\nSPIEL Wünsche Farbe");
		kartensatz.SetWunschfarbe(farbe);
		alternieren(dashboard);
		dashboard.aktualisiereGUI();
	}
	
	
	/**
	   * setzt Effekt-Variablen und Wunschfarbe für einen Wünscher vom Spieler, ruft Farbauswahl für Spieler-Wünscher auf
	   */
	private void effekteSetzen() {
		if(spielGewonnen) return;
		gelegterWert = kartensatz.getKarte(kartensatz.getletzteKarte()).getWERT();
		if(gelegterWert == Wert.ACHT) {//Aussetzen
			aussetzen = true;
		}
		if(gelegterWert == Wert.SIEBEN) {//Ziehen
			zwei_ziehen = true;
			kartenZiehen += 2;
		}
		if(gelegterWert == Wert.BUBE) {//Wünscher
			if(amZug == Spieler.COMPUTER) {//Wunschfarbe durch PC wird gesetzt
				kartensatz.SetWunschfarbe(computerGegner.farbeAussuchen(kartensatz));
			}
			else { //Wunschfarbe durch Spieler setzen
				dashboard.showwunsch(true);
			}
		}
		if(debug) System.out.println("\nSPIEL Effekte gesetzt:\nSPIEL Aussetzen: " + aussetzen + "\nSPIEL Zwei_Ziehen: " + zwei_ziehen + "\nSPIEL Anzahl: " + kartenZiehen);
	}	
}
