package uno;
import java.util.*;
import java.io.*;
import uno.card.*;
import uno.*;
import uno.Color.*;

public class Game{
	public static LinkedList<Card> getAllCards(){
		LinkedList<Card> ret = new LinkedList<>();
		//minden színből 2db-ot az 1 és 9 közötti lapokból, 1db-ot a 0-ás számozott lapból
		for(int i=1; i<9;i++){
			ret.add(new NumberCard(Color.GREEN,i));
			ret.add(new NumberCard(Color.BLUE,i));
			ret.add(new NumberCard(Color.YELLOW,i));
			ret.add(new NumberCard(Color.RED,i));
		}
		//2db letiltó, körfordító és +2-es lapot minden szinből.
		for(int i=0;i<2;i++){
			ret.add(new SkipCard(Color.GREEN));
			ret.add(new SkipCard(Color.BLUE));
			ret.add(new SkipCard(Color.YELLOW));
			ret.add(new SkipCard(Color.RED));
			ret.add(new ReverseCard(Color.GREEN));
			ret.add(new ReverseCard(Color.BLUE));
			ret.add(new ReverseCard(Color.YELLOW));
			ret.add(new ReverseCard(Color.RED));
			ret.add(new TakeTwoCard(Color.GREEN));
			ret.add(new TakeTwoCard(Color.BLUE));
			ret.add(new TakeTwoCard(Color.YELLOW));
			ret.add(new TakeTwoCard(Color.RED));
		}
		ret.add(new NumberCard(Color.GREEN,0));
		ret.add(new NumberCard(Color.BLUE,0));
		ret.add(new NumberCard(Color.YELLOW,0));
		ret.add(new NumberCard(Color.RED,0));
		//4db joker és +4-es lapot.
		for(int i=0; i<4;i++){
			ret.add(new WildCard());
			ret.add(new TakeFourCard());
		}
		for(Card c: ret){
			//System.out.println(c);
		}
		return ret;
	}
	ArrayList<Player> players;
	int actualPlayer;
	LinkedList<Card> pile;
	LinkedList<Card> played;
	boolean forwardOrder;
	public Game(String[] names){
		players=new ArrayList<>();
		for(String s : names){
			players.add(new Player(s));
		}
		actualPlayer=0;
		pile=getAllCards();
		played=new LinkedList<>();
		forwardOrder=true;
	}
	public Player getActualPlayer(){
		return players.get(actualPlayer);
	}
	public void nextPlayer(){
		//System.out.println("\tnextPlayer begin "+actualPlayer);
		if(forwardOrder){
			actualPlayer++;
			if(actualPlayer>=players.size())actualPlayer=0;
		}else{
			actualPlayer--;
			if(actualPlayer<0)actualPlayer=players.size()-1;
		}
		//System.out.println("\tnextPlayer end "+actualPlayer);
	}
	public void reverseOrder(){
		forwardOrder=!forwardOrder;
	}
	public void putOnTop(Card c){
		played.push(c);
	}
	public void startGame(){
		pile=getAllCards();
		java.util.Collections.shuffle(pile);
		for(int i=0;i<6;i++){
			for(Player p : players){
				p.draw(nextCard());
			}
		}
		//Majd addig pakoljon a pakliból a kijátszott lapok kupacára, amíg nem jön egy számozott lap.
		//while()
	}
	public Card nextCard(){
		if(!pile.isEmpty())return pile.pop();
		else{
			Card save = played.pop();
			pile=played;
			java.util.Collections.shuffle(pile);
			played=new LinkedList<>();
			played.push(save);
			return pile.pop();
		}
	}
	//Legyen egy play() metódusa, ami elindítja a játékot.
	//A play metódus visszatérési értéke a győztes játékos neve.
	public String play(){
		Player p = null;
		do{
		System.out.println();
		p = players.get(actualPlayer);
		System.out.println("Aktualis jatekos: "+p.getName()+" ("+actualPlayer+")");
		//A játéknak akkor van vége, ha a soron következő játékos kezében nincsen lap (hasWon).
		if(p.hasWon()){
			System.out.println("Nyert!");
			return p.getName();
		}
		//A játék minden lépésben kiírja a legfelső kijátszott lapot,
		Card top = nextCard();
		System.out.println("legfelso kijatszott lap "+top);
		//majd az aktuális játékosnak szóló üzenetet (terminalMessage).
		System.out.println("aktualis jatekosnak szolo uzenet "+p.terminalMessage());
		//Ezután bekéri a játékos akcióját a konzolablakban
		System.out.println("kerem a jatekos akciojat a konzolablakban");
		String s = readLine();
		//(az adatbekérést a Game osztály egy védett readLine() függvényen keresztül végezzük
		//a System.in stream-ből). Ezt az aktuális játékos execute függvényének adja át,
		Card ret=p.execute(s, top);
		//ami választ egy lapot. Ha a lap null, vagy nem helyezhető el a legfelső kijátszott lapra,
		if(ret==null){
			//akkor az aktuális játékos a draw függvénnyel fölhúzza a pakli legfelső lapját
			Card draw=nextCard();
			p.draw(draw);
			System.out.println("aktualis jatekos felhuzza a pakli legfelso lapjat: "+draw);
			//és visszakapja azt is, amit lerakott.
			System.out.println("es visszakapja azt is, amit lerakott ");
			//p.draw(ret);
		}else{
			//Különben a lap kijátszásra kerül,
			//a joker lapokhoz bekérjük a választott színt, majd beállítjuk a lapon.
			if(ret.getClass()==WildCard.class){
				System.out.println("joker laphoz kerem a valasztott szint (GREEN, BLUE, YELLOW, vagy RED)");
				String color=readLine();
				switch(color){
					case "GREEN":
					((WildCard)ret).chooseColor(Color.GREEN);
					break;
					case "BLUE":
					((WildCard)ret).chooseColor(Color.BLUE);
					break;
					case "YELLOW":
					((WildCard)ret).chooseColor(Color.YELLOW);
					break;
					case "RED":
					((WildCard)ret).chooseColor(Color.RED);
					break;
				}
			}
			//Ezután a lap effect-je végrehajtódik,
			System.out.println("Ezutan a lap effect-je vegrehajtodik");
			ret.effect(this);
			//a lap a kijátszott lapok tetejére lesz helyezve.
			System.out.println("a lap a kijatszott lapok tetejere lesz helyezve");
			putOnTop(ret);
			//Akár húzás, akár kijátszás történt, ezután a következő játékos jön.
			System.out.println("kovetkezo jatekos jon.");
			nextPlayer();
			}
		}while(!p.hasWon());
		System.out.println("Vege...");
		return p.getName();
	}
	//(az adatbekérést a Game osztály egy védett readLine() függvényen keresztül végezzük a System.in stream-ből)
	protected String readLine(){
		try{
			return new BufferedReader(new InputStreamReader(System.in)).readLine();
		}catch(IOException ex){return "";}
	}
}