//
//
// gere le jeu, les parties, les sockets
//
//

import java.awt.Event;
import java.awt.Component;

public class Jeu1001b implements Runnable{
  //
  static int NORTH=0,EAST=1,SOUTH=2,WEST=3;
  int jActif=SOUTH;
  boolean jPresent[]={false,false,true,false};
  String joueur="";
  String jPseudo[]={"Nord", "Est", "Sud", "Ouest"};
  int jScore[]={0,0,0,0};

  // les cartes du jeu
  static int v200=3, v100=5, v75=6, v50=7, v25=9;
  static int roulez=10, stop=11, vLimite=12, finVLimite=13, essence=14, panneEssence=15;
  static int roueDeSec=16, creve=17, accident=18, reparation=19;
  static int prioritaire=8, increvable=4, asDuVolant=2, citerne =1;
  static String[] nomCarte={"","xtratank","driv_ace","200","punc_prf","100","75","50",
			    "rightway","25","roll","stop",
			    "spdlimit","endlimit","gasoline","outofgaz",
			    "spartire","flattire","accident","repair",""};

  // le jeu sur la table
  int jMain[]=new int[7];          // les cartes de la main du joueur
  int tableV200[]=new int[4];      // nb de cartes V200 qu'a etale chaque joueur
  int tableV100[]=new int[4];      // nb de cartes V100 qu'a etale chaque joueur
  int tableV75[]=new int[4];       // nb de cartes V75 qu'a etale chaque joueur
  int tableV50[]=new int[4];       // nb de cartes V50 qu'a etale chaque joueur
  int tableV25[]=new int[4];       // nb de cartes V25 qu'a etale chaque joueur
  int tableRoute[]=new int[4];     // la carte sur la route de chaque joueur
  int tableAtouts[]=new int[4];    // les atouts de chaque joueur
  int tableDerniereCarteJetee=0;   // la derniere carte jetee

  java.awt.Component partie;
  dialC dial;

  //mode de jeu
  int inPlay=0;
  static final int NEW_GAME=1, PIOCHE=2, JOUE=3, PATIENTE=4, NO_GAME=5, EXIT=6;
  // messages
  static final int CONNECT=0, NOM_JOUEURS=7, DISTRIB_CARTES=8, PIOCHEUR=9, PIOCHE_NOUVELLE=11, PIOCHE_DERNIERE=10;
  static final int RECU_CARTE=11, JOUE_CARTE=12, JETE_CARTE=13, CARTE_REFUSEE=14, FIN_PARTIE=15, ABANDON=16;

  protected String host=null;
  protected int port;

  Thread t;

  public Jeu1001b(Component c){
    partie=c;
    t=new Thread(this);
  }

  public void connect( String host, int port){
    this.host=host;
    this.port=port;
    playGame(CONNECT);    
    t.start();

  }

Event msgEvent = new Event(this,0,null);

  public void reportAction(int type,Object o){
    partie.action( new Event(this,type,o),o);
  }

  //  public void playGame(){
  //playGame(inPlay,"");
  //}
  public void playGame(int whatPlay){
    playGame(whatPlay,"");
  }

  public void playGame(int whatPlay,String args){
   int len;
   int ind;
   String msg=null; 
   String req=""; // requete
   String cmd=""; // la commande
   String rep=""; // pour la reponse
   int j=0;

   //while(inPlay>0){ 

   switch(whatPlay){
   case CONNECT:
     try{
       if(dial==null){
	 dial= new dialC(host,port);
	 // Tell the user that we've connected
	 msg="Vous etes maintenant connecte sur " + dial.s.getInetAddress().getHostName() +
	   ":"+ dial.s.getPort();
	 inPlay=NO_GAME;
       }else
	 msg="Vous etes deja connecte";
     }catch(Exception e) {msg="Erreur de connection:\n \n"+e+"\nAvez vous lance un serveur?";}; 
     reportAction(CONNECT,msg);
     break;
   case NEW_GAME:
     if (inPlay != NO_GAME){
       reportAction(NEW_GAME,
		    " Vous devez terminer la partie avant\nde debuter un nouveau jeu.");
       break;
     } else inPlay=NEW_GAME;

     joueur=args;
     dial.send("NewGame "+joueur);
     reportAction(NEW_GAME,null);
     
     break;
   case PIOCHE_NOUVELLE:
     dial.send("Pioche Nouvelle");
     break;
   case PIOCHE_DERNIERE:
     dial.send("Pioche Derniere");
     // print a prompt
     //System.out.print("Pioche Nouvelle ou Derniere ?> "); 
     //System.out.flush();
     //rep = dial.readLine();
     //dial.send("Pioche "+rep);
     // recoit la carte
     //parseMessage(dial.waitAndGetMessage()); 
     break;
   case JOUE_CARTE:
     dial.send("Joue "+args);
     inPlay=PATIENTE;
     break;
   case JETE_CARTE:
     // print a prompt
     //System.out.print("Joue C? J?/Jette C?> "); 
     //System.out.flush();
     //rep = dial.readLine();
     dial.send("Jete "+args);
     // recoit la reponse
     //parseMessage(dial.waitAndGetMessage());
     inPlay=PATIENTE;
     break;
   case ABANDON:
     if(inPlay==PIOCHE||inPlay==JOUE||inPlay==PATIENTE){
       dial.send("Abandonne");
     }else{
       reportAction(ABANDON,null);
     }
     break;
   case FIN_PARTIE:
     inPlay=NO_GAME;
     break;
   case EXIT:
     if(dial!=null) {
       dial.send("Quitte");
       dial=null;
     }
     inPlay=EXIT;
     reportAction(EXIT,null);
     break;
   default:
     System.out.println("Jeu1001b:Message non traite :Joueur:"+j+", etat:"+inPlay+", requete:"+req);
     inPlay=0;
   }
   
  }  


  public void run(){ // attend un message du serveur et notifie
    for (String msg="";;){
      msg=dial.waitAndGetMessage();
      if(msg==null) reportAction(EXIT,null);
      if (msg=="") System.err.println("Erreur: msg vide!!");
      parseMessage(msg); 
    }
  }

  static int getIdCarte(String nc){ // retourne l'identifieur de la carte
    for(int c=1;c<20;c++)
      if(nomCarte[c].equalsIgnoreCase(nc)) return c;
    return 0;
  }

  public void parseMessage(String msg){
   int len;
   int ind,deb=0;
   
   String cmd=""; // la commande
   String arg=""; // les arguments

    ind=msg.indexOf(' ');
    cmd=(ind==-1?msg:msg.substring(0, ind)); // la commande
    arg=(ind==-1?"":msg.substring(ind+1)); // les arguments

    if(cmd.equalsIgnoreCase("Joueurs")){
      System.err.println(":"+msg+":"+cmd+" "+arg);
      //determination de la position du joueur
      String nj[]=new String[4]; int nbj=0,pos=0;
      deb=0;ind=arg.indexOf(' ');
      for(int j=0;j<4;j++){
	if(ind==-1) {	
	  nj[j]=arg.substring(deb);nbj=j+1;
	  break;
	}
	nj[j]=arg.substring(deb,ind);
	deb=ind+1;ind=arg.indexOf(' ',deb);
      }
      for(int j=0;j<4;j++) 
	if(nj[j]!=null && nj[j].equalsIgnoreCase(joueur)) pos=j;
      System.err.println(":les noms:"+nj[0]+","+nj[1]+","+nj[2]+","+nj[3]+",nbj="+nbj+",pos="+pos);
      //nj[0]="arthur";nj[1]="basile";nj[2]="cretin";nj[3]="dede";nbj=2;pos=1;

      jPseudo[SOUTH]=nj[pos];
      if(nbj==2){
	jPseudo[NORTH]=nj[(pos+1)%2];
	jPseudo[EAST]="";
	jPseudo[WEST]="";
	jPresent[NORTH]=true;
	jPresent[EAST]=false;
	jPresent[WEST]=false;
      }else if(nbj==3){
	jPseudo[NORTH]="";
	jPseudo[EAST]=nj[(pos+2)%3];
	jPseudo[WEST]=nj[(pos+1)%3];
	jPresent[NORTH]=false;
	jPresent[EAST]=true;
	jPresent[WEST]=true;
      }else if(nbj==4){
	jPseudo[NORTH]=nj[(pos+2)%4];
	jPseudo[EAST]=nj[(pos+1)%4];
	jPseudo[WEST]=nj[(pos+3)%4];
	jPresent[NORTH]=true;
	jPresent[EAST]=true;
	jPresent[WEST]=true;
      }
      System.err.println(":les noms:"+jPseudo[0]+","+jPseudo[1]+","+jPseudo[2]+","+jPseudo[3]);
      reportAction(NOM_JOUEURS,arg);

    }else if(cmd.equalsIgnoreCase("Distribcartes")){
      System.out.println("::"+msg);
      int d=0, f=arg.indexOf(' ');
      for(int c=0;c<5;c++){
	jMain[c]=getIdCarte(arg.substring(d,f));
	d=f+1; f=arg.indexOf(' ',d+1);
      }
      jMain[5]=getIdCarte(arg.substring(d));;
      jMain[6]=0;
      for(int j=0;j<4;j++){
	tableV200[j]=0;             // nb de cartes V@00 qu'a etale chaque joueur
	tableV100[j]=0;             // nb de cartes V100 qu'a etale chaque joueur
	tableV75[j]=0;              // nb de cartes V75 qu'a etale chaque joueur
	tableV50[j]=0;              // nb de cartes V50 qu'a etale chaque joueur
	tableV25[j]=0;              // nb de cartes V25 qu'a etale chaque joueur
	tableRoute[j]=stop;            // la carte sur la route de chaque joueur
	tableAtouts[j]=0;           // les atouts de chaque joueur
	tableDerniereCarteJetee=0;  // la derniere carte jetee
      }
      reportAction(DISTRIB_CARTES,null);
      inPlay=PATIENTE; // Next step

    }else if(cmd.equalsIgnoreCase("Piocheur")){
      for(int j=0;j<4;j++) //determination du joueur actif
	if(jPseudo[j].equalsIgnoreCase(arg)) {jActif=j; break;}
      reportAction(PIOCHEUR,null);

      // ci apres a supprimer
       if(jActif==SOUTH){
	 System.out.println("C'est a moi de jouer !!!!");
	 inPlay=PIOCHE; // Next step
       }else{
	 System.out.println("Patiente: "+msg);
	 inPlay=PATIENTE; // Next step
       }
    }else if(cmd.equalsIgnoreCase("Carte")){
      // identification de la carte recu (dans arg)
      jMain[6]=getIdCarte(arg);
      reportAction(RECU_CARTE,null);      
      System.out.println("::"+msg);// ci apres a supprimer
      inPlay=JOUE; // Next step

    }else if(cmd.equalsIgnoreCase("CarteRefusee")){
      jMain[6]=getIdCarte(arg);
      System.out.println("::"+msg);
      reportAction(CARTE_REFUSEE,null);
      inPlay=JOUE; // same step
      
    }else if(cmd.equalsIgnoreCase("CarteJetee")){
      tableDerniereCarteJetee=getIdCarte(arg);
      if(tableDerniereCarteJetee==0) System.err.println("Alerte:Erreur:Carte jetee non reconnue");
      System.out.println("::"+msg);
      inPlay=PATIENTE; // Next step
      
    }else if(cmd.equalsIgnoreCase("CarteJouee")){
      int c=arg.indexOf(' ');
      String nc=arg.substring(0,c); // nom de la carte
      String nj=arg.substring(c+1); // nom du joueur 
      c=getIdCarte(nc); //id carte
      int j=0; //id joueur
      for(j=0;j<4;j++)
	if(nj.equalsIgnoreCase(jPseudo[j])) break;
      // attribution de la carte
      if(c==v200) tableV200[j]++; 
      else if(c==v100) tableV100[j]++;
      else if(c==v75) tableV75[j]++; 
      else if(c==v50) tableV50[j]++; 
      else if(c==v25) tableV25[j]++;
      else if(c==prioritaire || c==increvable || c==asDuVolant || c==citerne) 
	tableAtouts[j]+=c;
      else  tableRoute[j]=c;

      System.out.println("::"+msg);
      inPlay=PATIENTE; // Next step
      
    }else if(cmd.equalsIgnoreCase("Abandonne")){
      inPlay=NO_GAME;
      reportAction(ABANDON,arg);
    }else if(cmd.equalsIgnoreCase("Gagnant")){
      inPlay=NO_GAME;
      reportAction(FIN_PARTIE,arg);
    }else
      System.out.println(":Message non traite:"+msg);
  }
}
