/**
 *
 * Les milles et une bornes
 *
 * @version 1.00 Mars 1997 
 * @author Laurent Courbet (courbet@essi.fr), Gilles Esmel (esmel@essi.fr)
 * 
 *
 *
 * Permission to use, copy, modify, and distribute this 
 * software and its documentation for NON-COMMERCIAL purposes
 * and without fee is hereby granted provided that this 
 * copyright notice appears in all copies. 
 * 
 * THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR 
 * WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS
 * AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED 
 * BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 
 * THIS SOFTWARE OR ITS DERIVATIVES.
 */
 

import java.awt.*;
import java.awt.image.*;
import java.net.*;
import java.io.*;
//import java.applet.Applet;
//import java.applet.AudioClip;
import gie.*;

public class Les1001bornes extends Frame{
     
  Jeu1001b jeu=new Jeu1001b(this); // le driver de jeu

  protected Image image;
  protected Image bgImage;
  protected Image[] playersImg=new Image[4];
  protected int bg_width = 0;
  protected int bg_height = 0;
  protected int bgPlayers=-3;

  // pioche
  static Image bgCarte;
  // whoPlay
  static Image whoPlayImg[]=new Image[4];
  static Image imgCarte[]=new Image[20];

  static int NORTH=0,EAST=1,SOUTH=2,WEST=3;
  String pseudo; String host; int port;

  String msg="Bienvenue ";
  MenuBar mm=null; // pour gerer l'affichage de la barre de menu

  // pour l'option des messages sonores
  boolean soundMsg=true;
  gie.Media errSound=new gie.Media("sound/nopossible.wav");


  // fond de carte nord
  static int bgCNx=260, bgCNy=144;
  static int bgCNtx[]={bgCNx+6,bgCNx+41,bgCNx+47,bgCNx+0};
  static int bgCNty[]={bgCNy+0,bgCNy+0,bgCNy+38,bgCNy+38};
  static Polygon bgCNorth=new Polygon(bgCNtx,bgCNty,4);
  // fond de carte est
  static int bgCEx=329, bgCEy=188;
  static int bgCEtx[]={bgCEx+0,bgCEx+73,bgCEx+100,bgCEx+10};
  static int bgCEty[]={bgCEy+0,bgCEy+0,bgCEy+27,bgCEy+27};
  static Polygon bgCEast=new Polygon(bgCEtx,bgCEty,4);
  // fond de carte ouest
  static int bgCWx=139, bgCWy=188;
  static int bgCWtx[]={bgCWx+26,bgCWx+96,bgCWx+87,bgCWx+0};
  static int bgCWty[]={bgCWy+0,bgCWy+0,bgCWy+27,bgCWy+27};
  static Polygon bgCWest=new Polygon(bgCWtx,bgCWty,4);

   static boolean showPl=false;
  static boolean showRNorth=false;
  static boolean showREast=false;
  static boolean showRWest=false;
  static boolean showMsg=false;

  Rectangle piocheDCJBox=new Rectangle(250,235,30,43);
  Rectangle piocheNCBox=new Rectangle(290,235,30,43);
  Rectangle menuBox=new Rectangle(120,250,40,30);

  protected int dragCarte=0; //lors du deplacemnet d'un carte
  protected Point dragCoord=new Point(0,0);


  //---------------------------------------------------------------

   public Les1001bornes(String pseudo,String host,int port){
     this.pseudo=pseudo;
     this.host=host;
     this.port=port;;
     setTitle("Les 1001 bornes : "+pseudo);
     msg=msg+pseudo;

     // chargement des images
     // ---------------------
     image = Toolkit.getDefaultToolkit().getImage("graphics/bk1001.gif"); //le fond
     // img players
     playersImg[NORTH]=Toolkit.getDefaultToolkit().getImage("graphics/jnorth.gif");
     playersImg[EAST]=Toolkit.getDefaultToolkit().getImage("graphics/jeast.gif");
     playersImg[WEST]=Toolkit.getDefaultToolkit().getImage("graphics/jwest.gif");
     // whoPlay
     whoPlayImg[NORTH]=Toolkit.getDefaultToolkit().getImage("graphics/north.gif");
     whoPlayImg[EAST]=Toolkit.getDefaultToolkit().getImage("graphics/east.gif");
     whoPlayImg[SOUTH]=Toolkit.getDefaultToolkit().getImage("graphics/south.gif");
     whoPlayImg[WEST]=Toolkit.getDefaultToolkit().getImage("graphics/west.gif");
     // pioche
     bgCarte=Toolkit.getDefaultToolkit().getImage("graphics/bgcarte.gif");
     // les cartes
     imgCarte[0]=Toolkit.getDefaultToolkit().getImage("graphics/cartes/roadcard.gif");
     for(int c=1; c<20;c++)
       imgCarte[c]=Toolkit.getDefaultToolkit().getImage("graphics/cartes/"+Jeu1001b.nomCarte[c]+".gif");
     
     //Set up the menu bar.
     // ---------------------
     MenuBar mb = new MenuBar();
     Menu m = new Menu("Menu");
     m.add(new MenuItem("Connection"));
     m.add(new MenuItem("-"));
     m.add(new MenuItem("Nouvelle partie"));
     m.add(new MenuItem("Abandonne partie"));
     m.add(new MenuItem("-"));
     m.add(new MenuItem("Bye bye"));
     mb.add(m);
     Menu m2 = new Menu("Options");
     m2.add(new CheckboxMenuItem("Messages sonores"));
     mb.add(m2);
     setMenuBar(mb);
     this.resize(579, 564);
     this.show();
     
     setBackground(new Color(191,128,102));
     setForeground(Color.white);
     this.repaint();
   }

   public boolean action(Event event, Object arg) {
     if (event.target instanceof MenuItem) { // les commandes par le menu
       String choix=(String)arg;
       if (choix.equals("Connection")) {
	 jeu.connect(host,port);

       }else if (choix.equals("Nouvelle partie")) {
	 if(jeu.inPlay==jeu.NO_GAME){
	   jeu.playGame(Jeu1001b.NEW_GAME,pseudo);
	 }

       }else if (choix.equals("Abandonne partie")) {
	 // if(jeu.inPlay==jeu.PIOCHE||jeu.inPlay==jeu.JOUE||jeu.inPlay==jeu.PATIENTE)
	   jeu.playGame(Jeu1001b.ABANDON);
	   // else
      }
       //else if (choix.equals("Configurer")) {
       // FileDialog fd = new FileDialog(this, "FileDialog");
       // fd.show();
       //}
       else if (choix.equals("Bye bye")) {
	 jeu.playGame(Jeu1001b.EXIT);
       }
       return true;
     }if (event.target instanceof Jeu1001b) { // les commandes par le jeu
       switch(event.id){
       case Jeu1001b.CONNECT:
	 showMsg((String)arg);
	 break;
       case Jeu1001b.NEW_GAME:
	 repaint();
	 if(arg==null)
	   showMsg("Patientez le temps que tous les joueurs soient prets !!");
	 else
	   (new InfoDialog(this, "Les 1001 bornes: nouveau jeu", (String)arg,"Suis-je bete!")).show();
	 break;
       case Jeu1001b.NOM_JOUEURS:
	 showMsg("Les joueurs sont:\n \n"+(String)arg);
	 bgPlayers++;
	 repaint(); // affichages des joueurs
	 break;
       case Jeu1001b.DISTRIB_CARTES:
	 repaint();
	 break;
       case Jeu1001b.PIOCHEUR:
	 repaint();
	 break;
       case Jeu1001b.RECU_CARTE:
	 repaint();
	 break;
       case Jeu1001b.CARTE_REFUSEE:
	 repaint();
	 break;
       case Jeu1001b.ABANDON:
	 if(arg==null)
	   (new InfoDialog(this, "Les 1001 bornes: Abandonne", 
			   "Il faut avoir commence une partie \npour pouvoir abandonner",
			   "Suis-je bete!")).show();
	 else if(arg.equals(jeu.jPseudo[SOUTH]))
	   showMsg("Partie terminee, j'abandonne!");
	 else
	   showMsg("Partie terminee, "+(String)arg+" abandonne!");
	 break;
       case Jeu1001b.FIN_PARTIE:
	 repaint();
	 (new InfoDialog(this, "Les 1001 bornes: Partie terminee", 
			 "le gagnant est "+(String)arg)).show();
	 showMsg("Partie terminee, le gagnant est "+(String)arg );
	 //showMsg("Partie terminee, le gagnant est "+(String)arg );
	 //repaint();
	 break;
       case Jeu1001b.EXIT:
	 System.exit(0);
	 break;
       }

       return true;
     }else if (event.target instanceof CheckboxMenuItem) { // les commandes par le menu
       soundMsg=!soundMsg;
     }

     return super.action(event, arg);
   }
   
   public boolean handleEvent(Event evt){
     if (evt.id == Event.WINDOW_DESTROY) System.exit(0);
      return super.handleEvent(evt);
   }

  void piochePaint(Graphics g){
    g.drawImage(bgCarte, 290, 235, this);//254
    if(jeu.tableDerniereCarteJetee!=0){
      g.drawRoundRect(250,235,30,43,5,5);
    }
    
  }
  void whoPlayPaint(Graphics g){
    //g.drawImage(whoPlayImg[jeu.jActif], 265, 188, this);
    g.drawImage(whoPlayImg[jeu.jActif], 265, 192, this);
  }
  Color cKm=new Color(191,128,102);
  void jGamePlay(Graphics g,int x, int y,int joueur){
    g.drawImage(imgCarte[0], x, y, this); //la route 
    int km=jeu.tableV200[joueur]*200+jeu.tableV100[joueur]*100+jeu.tableV75[joueur]*75+jeu.tableV50[joueur]*50+jeu.tableV25[joueur]*25;
    //Color fg=getForeground();
    Color fg=g.getColor();
    g.setColor(cKm);
    g.drawString(km+" Km",x+10,y+14); // affichage des km parcourus
    g.setColor(fg);
    g.drawImage(imgCarte[jeu.tableRoute[joueur]], x, y+16, this); //la signalisation
    int a=jeu.tableAtouts[joueur]; // les cartes atouts
    if((a & jeu.prioritaire)!=0) g.drawImage(imgCarte[jeu.prioritaire], x+80, y   , this);
    if((a & jeu.increvable)!=0)  g.drawImage(imgCarte[jeu.increvable],  x+80, y+16, this);
    if((a & jeu.asDuVolant)!=0)  g.drawImage(imgCarte[jeu.asDuVolant],  x+80, y+32, this);
    if((a & jeu.citerne)!=0)     g.drawImage(imgCarte[jeu.citerne],     x+80, y+48, this);
  }

  void jNorthPaint(Graphics g){
    if(showRNorth) jGamePlay(g,204,94,jeu.NORTH);
  }
  void jEastPaint(Graphics g){
    if(showREast) jGamePlay(g,315,153,jeu.EAST);
  }
  void jWestPaint(Graphics g){
    if(showRWest) jGamePlay(g,93,153,jeu.WEST);
  }

  void jSouthPaint(Graphics g){
    for (int c = 0; c < jeu.tableV200[jeu.SOUTH]; c++){ // carte v200
      g.drawImage(imgCarte[jeu.v200], 12, 410+8*c, this);
    }
    for (int c = 0; c < jeu.tableV100[jeu.SOUTH]; c++){ // carte v100
      g.drawImage(imgCarte[jeu.v100], 12+80, 410+8*c, this);
    }
    for (int c = 0; c < jeu.tableV75[jeu.SOUTH]; c++){ // carte v75
      g.drawImage(imgCarte[jeu.v75], 12+160, 410+8*c, this);
    }
    for (int c = 0; c < jeu.tableV50[jeu.SOUTH]; c++){ // carte v50
      g.drawImage(imgCarte[jeu.v50], 12+240, 410+8*c, this);
    }
    for (int c = 0; c < jeu.tableV25[jeu.SOUTH]; c++){ // carte v25
      g.drawImage(imgCarte[jeu.v25], 12+320, 410+8*c, this);
    }

    jGamePlay(g,12+400,410,jeu.SOUTH); // la route, les Km et les atouts

    if(jeu.inPlay==jeu.JOUE && dragCarte!=0){ //deplace carte
      g.drawImage(imgCarte[dragCarte], dragCoord.x-38, dragCoord.y-45, this);
    }
    for (int i = 0; i < 7; i++){ // les cartes de la main
      if (jeu.jMain[i]!=0) g.drawImage(imgCarte[jeu.jMain[i]], 12+i*80, 310, this);
    }
    

  }
  void showMsg(String msg){
    this.msg=msg;
    showMsg=true;
    repaint();
  }
  void hideMsg(){
    showMsg=false;
  }
   
  public boolean imageUpdate(Image img, int infoflags,
                              int x, int y, int width, int height){
    if ((infoflags & ImageObserver.ALLBITS) != 0){
      // image is complete     
      if(img==image){
	bg_width = image.getWidth(null);
	bg_height = image.getHeight(null);
	//resize(579, 364);
	//resize(bg_width, bg_height);
	     
      }else if(img==playersImg[NORTH] || img==playersImg[EAST] || img==playersImg[WEST]){
	bgPlayers++;      
      }
      repaint();
      return false;      
    } 
    
    return true; // want more info
   }

   public void update(Graphics g){
     paint(g);
   }

  // pour afficher les joueurs et leur cartes
  void bgRepaint(){
    bgImage =createImage(579,564);
    Graphics g=bgImage.getGraphics();
    g.drawImage(image, 0, 0, this);
    
    if(jeu.jPresent[NORTH]){
      g.drawImage(playersImg[NORTH], 191, 0, this);
      g.fillPolygon(bgCNorth);
      //gbg.drawString(msg,285-(getGraphics().getFontMetrics().stringWidth(msg)/2),298); // msg
      g.drawString(jeu.jPseudo[NORTH],200,167); 
    }
    if(jeu.jPresent[WEST]){
      g.fillPolygon(bgCWest);
      g.drawImage(playersImg[WEST], 6, 44, this);
      g.drawString(jeu.jPseudo[WEST],142,230); 
    }
    if(jeu.jPresent[EAST]){
      g.drawImage(playersImg[EAST], 380, 44, this);
      g.fillPolygon(bgCEast);
      g.drawString(jeu.jPseudo[EAST],340,230); 
    }
    g.dispose();
    image=bgImage;
    //playersImg=null;   
    
  }

   public void paint(Graphics g){ 

     if (bg_width <= 0 || bg_height <= 0){
       // pour preload
      bgImage =createImage(1,1);
      Graphics gbg=bgImage.getGraphics();
      gbg.drawImage(image, 0, 0, this);
      gbg.drawImage(playersImg[NORTH], 0, 0, this);
      gbg.drawImage(playersImg[WEST],  0, 0, this);
      gbg.drawImage(playersImg[EAST],  0, 0, this);

      gbg.dispose();
      // ceci permet d'attendre que l'image soit chargee
      // avant de l'afficher (avec utilisation de imageUpdate )
      g.drawString("Gilles et laurent présentent", 100,100);
      g.drawString(" Les milles et une bornes...", 100,125);
      return;
     }
     if(bgPlayers==1) 
       bgRepaint();
       
     bgImage =createImage(579,564);     // bgImage =createImage(bg_width, bg_height);
     Graphics gbg=bgImage.getGraphics();
     gbg.drawImage(image, 0, 0, this);
     
     whoPlayPaint(gbg); // indique celui qui joue
     
     piochePaint(gbg); // les (la) carte(s) de la pioche
     
     jSouthPaint(gbg); // la carte est
     gbg.drawString(msg,285-(getGraphics().getFontMetrics().stringWidth(msg)/2),298); // msg
     // cartes du jeu des autres
     if(jeu.jPresent[WEST]) jWestPaint(gbg);  // la carte ouest
     if(jeu.jPresent[NORTH]) jNorthPaint(gbg); // la carte nord
     if(jeu.jPresent[EAST]) jEastPaint(gbg);  // la carte est
     
     gbg.dispose();
     g.drawImage(bgImage, 0, 0, this);
   }
   

  protected int selCarteMain(int x, int y){
    if (y >= 310 && 400 >= y ) {// cartes de la main
      for (int c = 0; c < 7; c++) {//recherche de la carte a deplacer
	if (x>=(12+80*c) && (88+80*c)>=x) 
	  return c; //carte trouve
      }
    }
    return -1;
  }

  protected boolean jNorthCard(int x, int y){
    return (jeu.jPresent[NORTH]?bgCNorth.inside(x,y):false);
  }
  protected boolean jEastCard(int x, int y){
    return (jeu.jPresent[EAST]?bgCEast.inside(x,y):false);
  }
  protected boolean jSouthCard(int x, int y){
    if (y >= 410 && 500 >= y && x>=12 && (12+80*7)>=x) 
      return true;
    return false;
  }
  protected boolean jWestCard(int x, int y){
    return (jeu.jPresent[WEST]?bgCWest.inside(x,y):false);
  }

   public boolean mouseUp(Event evt, int x, int y) {
     if(jeu.inPlay==jeu.JOUE ){ //joue carte
       if(dragCarte!=0) { // une carte s'est deplace
	 if(jNorthCard(x, y)){ // carte mise sur joueur nord
	   jeu.playGame(jeu.JOUE_CARTE,Jeu1001b.nomCarte[dragCarte]+" "+jeu.jPseudo[jeu.NORTH]);

	 }else if(jEastCard(x, y)){ // carte mise sur joueur est
	   jeu.playGame(jeu.JOUE_CARTE,Jeu1001b.nomCarte[dragCarte]+" "+jeu.jPseudo[jeu.EAST]);

	 }else if(jSouthCard(x, y)){ // carte mise sur joueur sud
	   jeu.playGame(jeu.JOUE_CARTE,Jeu1001b.nomCarte[dragCarte]+" "+jeu.jPseudo[jeu.SOUTH]);

	 }else if(jWestCard(x, y)){ // carte mise sur joueur ouest
	   jeu.playGame(jeu.JOUE_CARTE,Jeu1001b.nomCarte[dragCarte]+" "+jeu.jPseudo[jeu.WEST]);

	 }else if(piocheNCBox.inside(x,y) || piocheDCJBox.inside(x,y)){ // carte jetee
	   jeu.playGame(jeu.JETE_CARTE,Jeu1001b.nomCarte[dragCarte]);

	 }else { // carte mise nulle part
	   for(int c=0;c<7;c++) if(jeu.jMain[c]==0){jeu.jMain[c]=dragCarte; break;} 
 
	 }
	 //arrange le jeu
	 for(int c=0;c<6;c++) if(jeu.jMain[c]==0){
	   jeu.jMain[c]=jeu.jMain[c+1];jeu.jMain[c+1]=0 ;
	 }  
	 dragCarte=0;
	 setCursor(Frame.DEFAULT_CURSOR);
	 repaint();
	 return true;
       }
     }
     return false;
   }

   public boolean mouseDown(Event evt, int x, int y) {
     if(evt.clickCount >= 2){
       if(menuBox.inside(x,y)){//show/hide menu
	 if(mm==null){
	   mm=getMenuBar();setMenuBar(null); 
	 }else{ 
	   setMenuBar(mm);mm=null; 
	 }
	 return true;
       }
       if(jeu.inPlay==jeu.PIOCHE) {//pioche 

	 if(piocheNCBox.inside(x,y)) {//pioche nouvelle carte
	   jeu.playGame(jeu.PIOCHE_NOUVELLE);
	   return true;
	 }
	 if(jeu.tableDerniereCarteJetee!=0 && piocheDCJBox.inside(x,y)){ //pioche derniere carte
	   jeu.playGame(jeu.PIOCHE_DERNIERE);
	   return true;
	 }
       }
     }
     if(jeu.inPlay==jeu.PIOCHE && selCarteMain(x,y)>=0){ // selectionner une carte sans avoir piocher
       if (soundMsg) errSound.play();
       showMsg("Vous devez piocher avant de jouer !!");
       return true;
	 
     }
     if(jeu.inPlay==jeu.JOUE ){ //selectionne carte a jouer
     
       int c=selCarteMain(x,y);
       if (c>=0 ) {// cartes de la main selectionnee?
	 dragCarte=jeu.jMain[c];  jeu.jMain[c]=0;
	 dragCoord.x=x; dragCoord.y=y;
	 setCursor(Frame.HAND_CURSOR); 
	 return true;
       }
     }
     return super.mouseDown(evt,x,y);;
   }

  public boolean mouseDrag(Event evt, int x, int y) {
    if(jeu.inPlay==jeu.JOUE && dragCarte!=0){ //deplace carte
      dragCoord.x=x; dragCoord.y=y;
      repaint();
      return true;      
    } 
    return super.mouseDrag( evt,  x,  y);
   }
  
   public boolean mouseMove(Event evt, int x, int y) {
     if(jeu.tableDerniereCarteJetee!=0){
       if(piocheDCJBox.inside(x,y) && !showPl){
	 getGraphics().drawImage(imgCarte[jeu.tableDerniereCarteJetee], 190, 234, this);
	 showPl=true;
	 return true;
       }
       if(showPl && !piocheDCJBox.inside(x,y))  {
	 showPl=false;
	 repaint();
	 return true;
       }
     }
     // voir la carte de l'adversaire north
     if(jeu.jPresent[NORTH]){
       if(bgCNorth.inside(x,y) && !showRNorth){
	 //getGraphics().drawImage(imgCarte[jeu.tableRoute[NORTH]], 260, 144, this);
	 showRNorth=true;
	 repaint();
	 return true;
       }else if(showRNorth && !bgCNorth.inside(x,y))  {
	 showRNorth=false;
	 repaint();
	 return true;
       }
     }
     // voir la carte de l'adversaire east
     if(jeu.jPresent[EAST]){
       if(bgCEast.inside(x,y) && !showREast){
	 //getGraphics().drawImage(imgCarte[jeu.tableRoute[EAST]], 329, 188, this);
	 showREast=true;
	 repaint();
	 return true;
       }else if(showREast && !bgCEast.inside(x,y))  {
	 showREast=false;
	 repaint();
	 return true;
       }
     }
     // voir la carte de l'adversaire west
     if(jeu.jPresent[WEST]){
       if(bgCWest.inside(x,y) && !showRWest){
	 //getGraphics().drawImage(imgCarte[jeu.tableRoute[WEST]], 139, 188, this);
	 repaint();
	 showRWest=true;
	 return true;
       }else if(showRWest && !bgCWest.inside(x,y))  {
	 showRWest=false;
	 repaint();
	 return true;
       }
     }
     
     return false;
   }

  public boolean keyDown(Event evt,int key){
    showRWest=true; showREast=true; showRNorth=true;
    repaint();
    return true;
  }
  public boolean keyUp(Event evt,int key){
    showRWest=false; showREast=false; showRNorth=false;
    repaint();
    return true;
  }

  //=================================================================================



   public static void main(String args[]){
     int port=0;
     String host=null;
     String pseudo=null;
     
     try{
       pseudo=args[2]; port=Integer.parseInt(args[1]); host=args[0]; 
     }catch(Exception e){
        port= 6789;
	try{
	  pseudo=args[1];host=args[0]; 
	}catch(Exception e1){
	  host="127.0.0.1";
	  try{
	    pseudo=args[0];
	  }catch(Exception e2){
	    System.out.println("\nSyntax error, the good syntax is:\n\n"+
			       "java Les1001bornes [serverName[ port]] pseudo_Du_Joueur\n\n");
	    System.exit(0);
	  }
	}
     }
     Frame f = new Les1001bornes(pseudo,host,port);
     //(new gie.Media("sound/adamdave.wav")).play(); // music d'intro
   }
}



                        
