/**
*Programme cree par The Cluster
*Classe JoueurM ( joueur manuel ) du jeu "Chkoba"
*@author The Clusters
*@version 1.0
**/

package chkoba;
import chkoba.*;
import java.util.*;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
*	Classe Joueur Manuel
*/

public class JoueurMImpl extends JoueurImpl implements IJoueurM
{
	/**
	* CONSTRUCTEURS
	**/
	
	/**
	*Constructeur avec le nom en parametre
	*@param n , nom du joueur
	*/
	public JoueurMImpl(String n) throws RemoteException
	{
		super(n);
	}
	
	/**
	*Constructeur par defaut
	*/
	public JoueurMImpl() throws RemoteException
	{
		super();
	}
	
	
	/**
	* METHODES
	**/
	
	/**
	*Permet de "jouer"
	*Methode ayant servi pour le console
	*/
	public void jouer(IPlateau plateau) throws RemoteException
	{
		int choix=0;
		boolean resultCarte=true;
		boolean bool=false;
		boolean mainvide=false;
		ArrayList<ICarte> choix_carte=new ArrayList<ICarte>();

		int carteMax=15; 				//nombre de cartes maximums pouvant être prises.
		
		System.out.println("Voici le tapis : ");
		System.out.println(plateau.getTapis().affiche());
		
		if ( !main.estVide() )
		{
			System.out.println(this.getNom()+", c'est a vous de jouer !");
			System.out.println("Voici votre main");
			System.out.println(main.affiche());
			System.out.println("");
			
			while(bool==false)
			{
			
				System.out.println("Voulez-vous poser une carte (0) ou prendre des carte du tapis (1)?");			
				choix=Lire.entier();
				
				if( choix ==0 | choix ==1 )
				{
					if(choix<=main.size())
					{
						bool=true;
					}				
				}
				else
				{
					System.out.println ("Rentrez une autre valeur celle ci n'est pas proposee");
				}
			}
			
			switch ( choix )
			{
				case 0 :
					this.poser(plateau);
					break;
				
				default :
					this.prendre(plateau, carteMax);
					break;
			}
		}
		else
		{
			System.out.println(this.getNom()+" vous ne pouvez plus jouer. Vous n'avez plus de cartes en main");
		}
	}
	
	/**
	*Poser une carte
	*Toujours en console
	*/
	public void poser( IPlateau plateau ) throws RemoteException
	{
		int choix;
		System.out.println("Vous posez une carte");
		System.out.println("Quelle carte voulez-vous poser?");
		choix=Lire.entier();
		
		while ( choix > main.size() || choix == 0 )
		{
			System.out.println("Mauvais numero de carte");
			System.out.println("Quelle carte de votre main voulez-vous poser?");
			choix=Lire.entier();
		}
		choix--;
		plateau.getTapis().add( main.get(choix) );
		main.remove(choix);
	}
	
	/**
	*Methode prendre pour console
	*/
	public void prendre(IPlateau plateau, int carteMax)
	{
		int nbCartes, carte, somme=0, choix;
		ArrayList<ICarte> choix_carte=new ArrayList<ICarte>();
		boolean b;
		ICarte c, tmp;
		
		try
		{
			
			//attention faux
			c=new CarteImpl();
			carteMax=this.coupsPossibles(c,plateau);
			
			if(carteMax == 0 )
			{
				System.out.println("Vous ne pouvez pas prendre de carte, aucune combinaison n'est disponible.");
				System.out.println("Vous aller devoir poser une carte de votre main");
				this.poser(plateau);
			}
			
			System.out.println("Vous prennez une carte du tapis");
			System.out.println("Quelle carte de votre main voulez-vous utiliser?");
			choix=Lire.entier();
			
			while ( choix > main.size() || choix == 0 )
			{
				System.out.println("Mauvais numero de carte");
				System.out.println("Quelle carte de votre main voulez-vous poser?");
				choix=Lire.entier();
			}
		
			choix--;
			c=plateau.getJoueurCourant().getMain().get(choix);
			System.out.println("Vous allez poser la carte "+c.getNom()+" de "+c.getCoul());
			System.out.println("Cartes max que vous pouvez prendre : "+carteMax);
			
			do
			{				
				do
				{
					System.out.println("Combien de cartes voulez vous prendre?"); 
					nbCartes=Lire.entier();
					
				}while(nbCartes > plateau.getTapis().size() || nbCartes >carteMax);
				
				do
				{
					if ( somme >c.getValeur() )
					{
						System.out.println("La valeur est trop elevee");
						System.out.println("Choisissez une autre combinaison");
						somme=0;
					}
					
					do
					{
						System.out.println("Quelle(s) carte(s) voulez vous prendre");
						carte=Lire.entier();
						
					}while(carte > plateau.getTapis().size());
					
					carte--;
					
					tmp=plateau.getTapis().get(carte);
					choix_carte.add(tmp);
					b=plateau.getTapis().remove(tmp);
					
					somme+=choix_carte.get(choix_carte.indexOf(tmp)).getValeur();
					System.out.println("Valeur des cartes: "+somme);
					System.out.println("carte choisi: "+c.getValeur());
					
					//J'adore les couleurs de ce System.out.println() : ROSE POWAA!!!
					System.out.println("Sur le tapis, il reste\n "+plateau.getTapis().affiche());
					
				}while(somme != c.getValeur() );
				
			}while(somme != c.getValeur() ||  nbCartes !=carteMax);
			
			for (int n=0; n<nbCartes; n++)
			{
				plis.add(choix_carte.get(n));
				if ( b )
					this.chkoba();
			}
			
			plis.add(main.get(choix));
			main.remove(choix);
			
			for (int o=0; o<nbCartes-1; o++)
			{
				choix_carte.remove(o);
			}
			
			// Gestion des cartes multiples
			System.out.println(c.affiche());				
			System.out.println("Plis "+affichePlis());
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}	
	
	/**
	* Verifie si l'on peut prendre deux cartes
	* avec celle dans la main
	*@param c , carte que lon veut tester
	*@param plateau , le plateau connaissant tous les objets
	*/ 
	public boolean deuxCartes (ICarte c, IPlateau plateau) throws RemoteException
	{
		int i, j; // indices permettant de parcourir 2 a 2 le tapis
		int size=plateau.getTapis().size(); //taille du tapis
		
		for (i=0;i<size;i++)
		{
			for(j=0;j<size;j++)
			{
				if(j!=i) // on verifie que l'indice des 2 cartes du tapis est different
				{
					//si la valeur de la carte est egale a la somme des 2 cartes on retourne true.
					if(c.getValeur()==(plateau.getTapis().get(i).getValeur()+plateau.getTapis().get(j).getValeur()))
						return true;
				}
			}
		}
		return false;
	}
	
	/**
	* Verifie si l'on peut prendre trois cartes
	* avec celle dans la main
	*@param c , carte que lon veut tester
	*@param plateau , le plateau connaissant tous les objets
	*/ 
	public boolean troisCartes(ICarte c, IPlateau plateau) throws RemoteException
	{
		int i, j,k; // indices permettant de parcourir 3 a 3 le tapis
		int size=plateau.getTapis().size();//taille du tapis
		
		for (i=0;i<size;i++)
		{
			for(j=0;j<size;j++)
			{
				for(k=0;k<size;k++)
				{
					if(k!=i && k!=j && j!=i) // on verifie que l'indice des 3 cartes du tapis est different
					{
						//si la valeur de la carte est egale a la somme des 3 cartes on retourne true.
						if(c.getValeur()==(plateau.getTapis().get(i).getValeur()+plateau.getTapis().get(j).getValeur()+plateau.getTapis().get(k).getValeur()))
							return true;
					}
				}
			}
		}
		return false;
	}
	
	/**
	* Verifie si l'on peut prendre quatre cartes
	* avec celle dans la main
	*@param c , carte que lon veut tester
	*@param plateau , le plateau connaissant tous les objets
	*/ 
	public boolean quatreCartes(ICarte c, IPlateau plateau) throws RemoteException
	{
		int i, j,k,l; // indices permettant de parcourir 4 a 4 le tapis
		int size=plateau.getTapis().size(); //taille du tapis
		
		for (i=0;i<size;i++)
		{
			for(j=0;j<size;j++)
			{
				for(k=0;k<size;k++)
				{
					for(l=0;l<size;l++)
					{
						if(l!=i && l!=j && l!=k && k!=i && k!=j && j!=i) // on verifie que l'indice des 4 cartes du tapis est different
						{
							//si la valeur de la carte est egale a la somme des 4 cartes on retourne true.
							if(c.getValeur()==(plateau.getTapis().get(i).getValeur()+plateau.getTapis().get(j).getValeur()+plateau.getTapis().get(k).getValeur()+plateau.getTapis().get(l).getValeur()))
								return true;
						}
					}
				}
			}
		}
		return false;
	}
	
	/**
	* Verifie si l'on peut prendre cinq cartes
	* avec celle dans la main
	*@param c , carte que lon veut tester
	*@param plateau , le plateau connaissant tous les objets
	*/ 
	public boolean cinqCartes(ICarte c, IPlateau plateau) throws RemoteException
	{
		int i, j,k,l,m; // indices permettant de parcourir 5 a 5 le tapis
		int size=plateau.getTapis().size(); //taille du tapis
		
		for (i=0;i<size;i++)
		{
			for(j=0;j<size;j++)
			{
				for(k=0;k<size;k++)
				{
					for(l=0;l<size;l++)
					{
						for(m=0;m<size;m++)
						{
							if(m!=i && m!=j && m!=k && m!=l && l!=i && l!=j && l!=k && k!=i && k!=j && j!=i) // on verifie que l'indice des 3 cartes du tapis est different
							{
								//si la valeur de la carte est egale a la somme des 5 cartes on retourne true.
								if(c.getValeur()==(plateau.getTapis().get(i).getValeur()+plateau.getTapis().get(j).getValeur()+plateau.getTapis().get(k).getValeur()+plateau.getTapis().get(l).getValeur()+plateau.getTapis().get(m).getValeur()))
									return true;
							}
						}
					}
				}
			}
		}
		return false;
	}
	
	/**
	* Verifie si l'on peut prendre six cartes
	* avec celle dans la main
	*@param c , carte que lon veut tester
	*@param plateau , le plateau connaissant tous les objets
	*/ 
	public boolean sixCartes(ICarte c, IPlateau plateau) throws RemoteException
	{
		int i, j,k,l,m,n; // indices permettant de parcourir 6 a 6 le tapis
		int size=plateau.getTapis().size(); //taille du tapis
		
		for (i=0;i<size;i++)
		{
			for(j=0;j<size;j++)
			{
				for(k=0;k<size;k++)
				{
					for(l=0;l<size;l++)
					{
						for(m=0;m<size;m++)
						{
							for(n=0;n<size;n++)
							{
								if(n!=i && n!=j && n!=k && n!=l && n!=m && m!=i && m!=j && m!=k && m!=l && l!=i && l!=j && l!=k && k!=i && k!=j && j!=i) // on verifie que l'indice des 3 cartes du tapis est different
								{
									//si la valeur de la carte est egale a la somme des 6 cartes on retourne true.
									if(c.getValeur()==(plateau.getTapis().get(i).getValeur()+plateau.getTapis().get(j).getValeur()+plateau.getTapis().get(k).getValeur()+plateau.getTapis().get(l).getValeur()+plateau.getTapis().get(m).getValeur()+plateau.getTapis().get(n).getValeur()))
										return true;
								}
							}
						}
					}
				}
			}
		}
		return false;
	}
	
	
	/**
	*Verification des coups possibles a jouer et mise en place de contraintes pour prendre n cartes.	
	*/
	public int coupsPossibles( ICarte c,IPlateau plateau ) throws RemoteException
	{
		int carteMax=0;		
		try
		{
			for (int j=0; j<plateau.getTapis().size(); j++)
			{
				if(c.getValeur() == plateau.getTapis().get(j).getValeur())
				{
					carteMax=1;
					break;
				}
			}
			
			if ( carteMax==0)
			{
				for ( int i=0; i<plateau.getJoueurCourant().getMain().size();i++)
				{
					if ( c.getValeur() == 10 && plateau.getTapis().somme() == 10 && plateau.getTapis().size() == 7 )
						carteMax=7;
					else
					{
						if(deuxCartes(c,plateau) && carteMax<2 )
						{
							carteMax=2;
							break;
						}
						else if(troisCartes(c,plateau) && carteMax<3 )
						{							
							carteMax=3;
							break;
						}
						else if(quatreCartes(c,plateau) && carteMax<4 )
						{
							carteMax=4;
							break;
						}
						else if(cinqCartes(c,plateau) && carteMax<5 )
						{
							carteMax=5;
							break;
						}
						else if(sixCartes(c,plateau) && carteMax<6 )
						{
							carteMax=6;
							break;
						}
					}
				}
			}
		}
		catch(Exception e) 
		{
			e.printStackTrace();
		}
		return carteMax;
	}	
	
	/**
	* AFFICHAGE 
	**/
	
	/**
	*Affichage du nom du joueur
	*/
	public String affiche() throws RemoteException
	{
		String s="";
		
		s+="Joueur "+getNom();
		
		return s;
	}
	
	/**
	*Affichage des plis du joueur
	*/
	public String affichePlis() throws RemoteException
	{
		String s="";
		s+="\n";
		
		for(int i=0;i<plis.size();i++) 
			s+="\t"+plis.get(i).affiche(); 
		return s;
	}
}
