//Vous pouvez utiliser la commande javadoc *.java pour créer une API de notre programme (description de classes, des méthodes...). La compilation de notre programme se fait avec la commande javac *.java. Pour lancer le programme taper java Simulation

import java.util.*;
import java.io.*;
import java.util.StringTokenizer;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.BorderFactory; 
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
/**Permet de lancer une simulation d'une liaison HDLC. Les résulats de la simulation sont écrits dans un fichier texte se nommant "resultats"+nième simulation+".txt, se trouvant dans le repertoire courant de l'application. L'affichage des résultats se fait sur la sortie standard (dans le cas d'ereurs d'entrée sortie) ainsi que dans la fenêtre graphique.
 *@author Julien VAN DEN BOSSCHE / Benoît MOULIN   cmoi__at__julienvdb__dot__com / bmoulin@etu.info.unicaen.fr
 */
public class Simulation{
    //des composants graphiques pour l'interface
    Frame fenetre;  
    JPanel panel;   
   
    JPanel panelBas;
    JPanel panelHaut;
    JPanel panelCentral;
    JLabel label4 = new JLabel("                                                                                                                                                                                                                                                                   ");
    JTextField champURL;
    JTextArea fichier1;
    JTextArea fichier2;
    JTextArea fichier3;
    JButton boutonSimul;
    Liaison liaisonHDLC;    //la liaison HDLC qui va être simulée
    Vector vl;             //un vecteur qui permettra de stocker provisoirement les voies logiques 
    Vector donneesX25 = new Vector(); //stocke chaque info d'une ligne du fichier d'entrée dans un vecteur
    int numeroDepart = 1;             //le numéro de l'extrémité qui communique en premier : 1 par défaut 
    int nbSim;                        //un compteur qui permet de connaître le nombre de simulation effectuées
    Vector vecteurCV = new Vector();  //les circuits virtuels créés

    /**le constructeur qui crée un objet Simulation*/
    public Simulation(){
	nbSim=0;
    }
    /**permet de lire une ligne d'en extraire les données et les placer dans un vecteur
     *@param donnees la ligne qui constitue l'ensemble de données
     */
    public Vector litDonnees(String donnees){
	donneesX25.removeAllElements();
	String extrem = donnees.substring(0,1);  //on extrait l'extrémité de la liaison
	donneesX25.addElement(extrem);           //on l'insére dans le vecteur
	String reste = donnees.substring(2,donnees.length());
	StringTokenizer line = new StringTokenizer(reste,","); //on va insérer tous les tokens entre virgules 
	while(line.hasMoreTokens()){		
	    String token = line.nextToken();
	    donneesX25.addElement(token);
	}
	return donneesX25;   //on renvoie le vecteur (de chaîne de caractères)
    }
    
    /**permet de transformer un vecteur de chaîne de caractères en PaquetX25, ce paquet sera inséré dans un des deux vecteurs contenant soit les infos à transfèrer à l'extrémité 1 de la liaison ou soit à l'extrémité 2 de la liaison
     *@param d le vecteur de chaîne de caractères à traiter
     */
   
    public void transformeEnX25(Vector d){
	PaquetX25 donneesX25;  //le paquetX25 que l'on va construire
	Extremite e;  //on récupère l'objet Extremite correspondant
	if(d.elementAt(0).toString().equals("1")){
	    e = liaisonHDLC.getExtremite(1);
	}
	else{
	    e = liaisonHDLC.getExtremite(2);
	}

	//si on se trouve dans le cas d'une demande autre que envoi de données ou DL
	if(d.elementAt(1).toString().substring(0,1).equals("@")){
	    AdresseX25 adr1 = new AdresseX25(d.elementAt(1).toString());  //on crée les adresses X25
	    AdresseX25 adr2 = new AdresseX25(d.elementAt(2).toString());
	    //on recherche l'indice de la VL correspondant au nom qui se trouve dans le vecteur
	    String nom = d.elementAt(3).toString();
	    int ind=0;
	    int cpt2=0;
	    for(Iterator it = vl.iterator(); it.hasNext();){
		String nomVL2 = ((Voie)it.next()).getNom();
		if(nomVL2.equals(nom)){
		    ind = cpt2;
		}
		cpt2++;
	    }
	    //la voie pour le paquet à créer  
	    Voie v =(Voie)vl.elementAt(ind);
	    //les données du paquet	
	    String d2 = d.elementAt(4).toString();
	    //Création du PaquetX25
	    donneesX25 = new PaquetX25(e, adr1, adr2, v, d2);
	}
	//dans le cas d'un envoi de données ou DL (1-#A,DL ou 1-#A,1/0/0)
	else{
	    String nom = d.elementAt(1).toString();
	    int ind=0;
	    int cpt2=0;
	    for(Iterator it = vl.iterator(); it.hasNext();){
		String nomVL2 = ((Voie)it.next()).getNom();
		if(nomVL2.equals(nom)){
		    ind = cpt2;
		}
		cpt2++;
	    }
	    Voie v =(Voie)vl.elementAt(ind);
	    String d2 = d.elementAt(2).toString();
	    donneesX25 = new PaquetX25(e,v, d2);
	}
	//le paquet créer sera insérer dans le bon vecteur : un vecteur pour la transmission à partir de l'extrémité1 et 1 pour la transmission à partir de l'extrémité 2
	//c'est la liaison qui possède ces attributs
	if(d.elementAt(0).toString().equals("1")){
	    liaisonHDLC.addPourExtremite(1,donneesX25);
	   	}
	else{
	    liaisonHDLC.addPourExtremite(2,donneesX25);
	   	}
     }

    /**permet de traiter un fichier texte en entier contenant les données X25. Chaque ligne est transformée en PaquetX25.
     *@param url l'url du fichier à traiter
     */
    public void traiteFichier(String url){
	try{
	    BufferedReader fichier = new BufferedReader(new FileReader(url)); //ouverture du fichier
	    String ligne;
	    numeroDepart = (new Integer(fichier.readLine().substring(0,1))).intValue();
	    ligne = fichier.readLine();  //permet de lire une ligne
	    while((ligne = fichier.readLine()) != null){
		Vector vv = litDonnees(ligne);
		transformeEnX25(vv);
	    }
	}
	catch(FileNotFoundException err)
	    {
		System.err.println("Fichier non trouve !\n");
		System.err.println(err);
	    }
	catch(IOException err)
	    {
		System.err.println("Erreur d'IO\n");
		System.err.println(err);
	    }
    } 

/**permet de créer un fichier texte et d'écrire une ligne dedans. le fichier texte sera nommé "resultats"+la nième simulation que l'on fait+".txt"
     *@param l la ligne à écrire
     */

    public void ecrit(String l){
	try{
	    String s = "resultats"+nbSim+".txt";
	    FileWriter f = new FileWriter(s,true);
	    BufferedWriter b = new BufferedWriter(f);
	    PrintWriter out   = new PrintWriter(b);
	    out.println(l);
	    out.flush();
	    out.close();
	}
	catch(FileNotFoundException err){
	    System.err.println("Fichier non trouve !\n");
	    System.err.println(err);
	}
	catch(IOException err){
	    System.err.println("Erreur d'IO\n");
	    System.err.println(err);
	}
    } 

    /**permet de traiter l'emission d'un paquet X25 à une certaine position dans un vecteur.
     *@param v le vecteur de PaquetX25
     *@param indice l'indice du paquet à traiter
     *@param flagAck un booléen pour savoir s'il il faut mettre le bit PF à 1 quand on va encapsuler ce paquetX25 dans la trame HDLC
     */
     public void traiteVecteurX25(Vector v, int indice, boolean flagAcq){
	PaquetX25 paquetATraiter = (PaquetX25)v.elementAt(indice);
	String s1="";   //une chaîne permettant de stocker des infos d'affichage
	Extremite extrLiaison = paquetATraiter.getExtremite();
	Extremite extrOppose;
	//recherche de l'extrémité qui va recevoir la trame
	if(extrLiaison.getNumero() == 1){
	    extrOppose = liaisonHDLC.getExtremite(2);
	}
	else{
	    extrOppose =  liaisonHDLC.getExtremite(1);
	}
	int ind=0;
	int t = paquetATraiter.getType(); //recherche du type de paquet (envoi de données, de DL, ou établissement communication)
	//teste la disponibilité de la VL
	
	Voie v1 =  paquetATraiter.getVL();
	boolean b = v1.estLibre();
	
	   while(true){ 
	       //test si les voies sont bien nommées
	       boolean flagvoie = false; 
	       String nomvoie = paquetATraiter.getVL().getNom();
	       Vector v3 = liaisonHDLC.getVectorVL();
	       for(Iterator it = v3.iterator(); it.hasNext();){
		   if(nomvoie.equals(((Voie)it.next()).getNom())){
		       flagvoie = true;
		       break;
		   }
	       }
	       if(!flagvoie){
		   s1="Les noms des voies ne sont pas correctes : soit #A, #B, #C ou #D";
		   System.out.println(s1);
		   break;
	       }


	       if(t == 1){ //demande d'appel, confirmation appel
		   //test si on a respecté la numérotation des adresses	 
		   String num1 = (paquetATraiter.getAdresseRecepteur().getNom()).substring(1,(paquetATraiter.getAdresseRecepteur().getNom()).length());
		   
		   String num2 = (paquetATraiter.getAdresseEmetteur().getNom()).substring(1,(paquetATraiter.getAdresseEmetteur().getNom()).length());
		   
		   int numero1 = (new Integer(num1)).intValue();
		   int numero2 = (new Integer(num2)).intValue();
		   if((numero1 >9 || numero1 <0)||(numero2 >9 || numero2 <0)){
		       s1="Les adresses doivent être comprises entre 0 et 9";
		       System.out.println(s1);
		       fichier3.append(s1+"\n");
		       break;
		   }
		   //test si l'adresse du destinataire est de l'autre coté de la liaison	
		   AdresseX25[] tab = extrLiaison.getArrivants();
		   AdresseX25[] tab1 = extrOppose.getArrivants();
		   boolean flag = false;
		   boolean flag1 = false;
		   //regarde si l'emetteur se trouve bien avant la liaison
		   for(int i=0; i<tab.length; i++){
		       if((tab[i].getNom()).equals(paquetATraiter.getAdresseEmetteur().getNom())){
			   flag = true;
			   break;	      
		       }
		       else{
			   flag= false;
		       }
		   }
		   //regarde si le recepteur est joignable à partir de la liaison
		   for(int i=0; i<tab1.length; i++){
		       if((tab1[i].getNom()).equals(paquetATraiter.getAdresseRecepteur().getNom())){
			   flag1 = true;
			   break;	      
		       }
		       else{
			   flag1= false;
		       }
		   }
		   //envoi un message d'erreur
		   if(!flag || !flag1){
		       s1 ="Pas besoin de passer par la liaision pour envoyer un message de "+paquetATraiter.getAdresseEmetteur().getNom()+" au "+paquetATraiter.getAdresseRecepteur().getNom();
		       System.out.println(s1);
		       fichier3.append(s1+"\n");
		       break;
		   }

		   //si demande d'appel ou appel entrant
		   if((paquetATraiter.getDonnees().equals("A"))||(paquetATraiter.getDonnees().equals("AE"))){
		       if(!b){ //si la vl n'est pas libre
			  s1="La voie "+v1.getNom()+" est occupée";
			  System.out.println(s1);
			  fichier3.append(s1+"\n"); //fichier3 = le TextArea du milieu de la fenêtre
			  break;
		       }
		       else{        //sinon
			   String nomAction = paquetATraiter.getDonnees();
			   v1.changeEtat();   //on reserve la VL
			   //etablissement d'un cv
			   Cv circuit = new Cv(v1, paquetATraiter.getAdresseEmetteur(),paquetATraiter.getAdresseRecepteur());
			   vecteurCV.addElement(circuit);
			 
			   //la demande de réservation de ressources est traitée, on peut encapsuler le paquet
			   if(paquetATraiter.getDonnees().equals("A")){		  
			       s1="Demande d'appel sur la voie "+v1.getNom()+", "+v1.getNom()+" est libre.";
			       System.out.println(s1);
			       fichier3.append(s1+"\n");
			       TrameHDLC trame = extrLiaison.encapsule(paquetATraiter, flagAcq);
			       ecrit(trame.toString()); 
			       extrLiaison.envoiEncapsulation(extrOppose,trame);
			       break;
			   }
			   else{
			       s1="Appel entrant sur "+v1.getNom()+" de "+paquetATraiter.getAdresseRecepteur().getNom()+", "+v1.getNom()+" est libre";  
			       System.out.println(s1);
			       fichier3.append(s1+"\n");
			       TrameHDLC trame = extrLiaison.encapsule(paquetATraiter, flagAcq);
			       ecrit(trame.toString());
			       extrLiaison.envoiEncapsulation(extrOppose,trame);
			       break;
			   }
		       }
		   }
		   else{ //dans le cas des communications établies et accéptées, on encapsule directement car on a dèjà reservé la VL lors de l'appel. Dans la méthode boucle on s'assurera qu'il y ait eu un appel avant un CE ou CA
		       if(paquetATraiter.getDonnees().equals("CA")){
			   s1="Communication accéptée sur la voie "+v1.getNom(); 
			   System.out.println(s1);
			   fichier3.append(s1+"\n");
			   TrameHDLC trame = extrLiaison.encapsule(paquetATraiter, flagAcq);
			   ecrit(trame.toString());
			   extrLiaison.envoiEncapsulation(extrOppose,trame);
			   break;
		       }
		       if(paquetATraiter.getDonnees().equals("CE")){
			   s1="Communication établie sur la voie "+v1.getNom(); 
			   System.out.println(s1);
			   fichier3.append(s1+"\n");
			   TrameHDLC trame = extrLiaison.encapsule(paquetATraiter, flagAcq);
			   ecrit(trame.toString());
			   extrLiaison.envoiEncapsulation(extrOppose,trame);
			   break;
		       }
		   }
	       }
	       else{	//paquet de données à envoyer ou DL
		   if(!b){    //si la vl est prise avec une DL
		       if(paquetATraiter.getDonnees().equals("DL")){
			   //on libère le cv concerné et la vl car en libérant la vl on libère le cv (un cv possède une voie)
			   s1="La voie "+v1.getNom()+" était bien prise, on la libère";
			   v1.changeEtat();
			   System.out.println(s1);
			   fichier3.append(s1+"\n");
			   TrameHDLC trame = extrLiaison.encapsule(paquetATraiter, flagAcq);
			   ecrit(trame.toString());
			   extrLiaison.envoiEncapsulation(extrOppose,trame);
			   break;
		       }
		       else{ //sinon si ce n'est pas une DL on encapsule le paquetX25 et on l'envoi 
			   s1="La voie "+v1.getNom()+" est bien etablie, on transmet le paquet X25 : "+paquetATraiter.getDonnees();
			   System.out.println(s1);
			   fichier3.append(s1+"\n");
			   TrameHDLC trame = extrLiaison.encapsule(paquetATraiter, flagAcq);
			   ecrit(trame.toString());
			   extrLiaison.envoiEncapsulation(extrOppose,trame);
			   break;
		       }
		   }
		   if(b){ //dans le cas d'une VL libre avec une DL
		       if(paquetATraiter.getDonnees().equals("DL")){
			   s1="La voie "+v1.getNom()+" n'est pas prise, impossible de la libèrer";
			   System.out.println(s1);
			   fichier3.append(s1+"\n");
			   break;
		       }
		       else{ //dans le cas d'une VL libre avec un transfert de données
			   s1="Il n'y a pas de voie "+v1.getNom()+" établie pour transmettre : "+paquetATraiter.getDonnees();
			  System.out.println(s1);
			  fichier3.append(s1+"\n");
			  break;
		       }
		   }
	       }   
	   }
     }

   
    /**permet de traiter tous les paquets X25 à encapsuler. La choix du tour de parole entre l'extrémité 1 ou l'extrémité 2 se fait au hasard sauf pour la première transmission (on prend celui qui à envoyé SABM) et quand on a un paquet contenant CA ou CE sans avoir traiter l'appel avant on force à prendre le paquet de l'autre extrémité (celui qui contient A ou AE, notre fichier d'entrée étant considéré sans erreur). On force aussi quand une extrémité n'a plus rien à transmettre.
     */
    
    public void boucle(){
	String s3="";
	StringTokenizer s4;
	String s5="";
	int menExtr=0; //extremité retenu pour forcer le tour de parole quand on a eu RNR
	String memo=""; //permet de savoir si on a eu RNR
	int cpt=0;
	String s = "resultats"+nbSim+".txt";  //le nom du fichier de résultat
	File f = new File(s);
	String s1="";
  	f.delete();        //s'il existe on le supprime
	int indice1=0;
	int indice2 = 0;
	s1="****************************************************************************\n";
	s1+="*********************Début de traitement des trames X25*********************\n";
	s1+="****************************************************************************\n";
	System.out.println(s1);
	fichier3.append(s1+"\n");
	Extremite extremite1 = liaisonHDLC.getExtremite(1);
	    Extremite extremite2 = liaisonHDLC.getExtremite(2);
	    Vector pourExtremite1 = liaisonHDLC.getPourExtremite(1);
	    Vector pourExtremite2 = liaisonHDLC.getPourExtremite(2);
	while(true){
	    //si l'une ou l'autre des extrémité n'a plus rien à transmettre
	    if((pourExtremite1.size() == indice1) || (pourExtremite2.size() == indice2)){
		//on s'arrête les deux n'ont plus rien à transmettre
		if((pourExtremite1.size() == indice1) && (pourExtremite2.size() == indice2)){
		    s1="****************************************************************************\n";
		    s1+="**********************Fin de traitement des trames X25**********************\n";
		    s1+="****************************************************************************\n";
		   System.out.println(s1);
		   fichier3.append(s1+"\n");
		    break;
		} 
		else{  //si l'extrémité 1 n'a plus rien à transmettre alors c'est la 2 qui transmet
		    if(pourExtremite1.size() == indice1){
			//si le nombre de trame envoyées sans acq est 6 alors on met le bit pf à 1 (le flag true).
			//Comme l'extrémité 1 n'a plus rien à transmettre elle envoie une trame RR pour acquitter
			if(extremite2.getNbTrameSansAcq() == 6){
			    traiteVecteurX25(pourExtremite2, indice2, true);
			    indice2++;
			    TrameHDLC t = new TrameHDLC(extremite1, "RR", "0", (""+extremite1.getNumeroTrameRecu()));
			    ecrit(t.toString());
			    extremite1.envoiEncapsulation(extremite2, t);
			    extremite2.setNbTrameSansAcq(0);
			}
			else{ //sinon on va encapsuler "normalement", bit pf à 0
			    traiteVecteurX25(pourExtremite2, indice2, false);
			    indice2++;
			}
		    }
		    else{//le même schéma que pour l'extrémité 1 se produit pour l'extrémité 2
			if(pourExtremite2.size() == indice2){
			    if(extremite1.getNbTrameSansAcq() == 6){
				traiteVecteurX25(pourExtremite1, indice1, true);
				indice1++;
				TrameHDLC t = new TrameHDLC(extremite2, "RR", "0", (""+extremite2.getNumeroTrameRecu()));
				ecrit(t.toString());
				extremite2.envoiEncapsulation(extremite1, t);
				extremite1.setNbTrameSansAcq(0);
			    }
			    else{
				traiteVecteurX25(pourExtremite1, indice1, false);
				indice1++;
			    }
			}
		    }
		}
	    }
	    else{  //sinon si les 2 extrémités on des trames à transmettre, on tire un numéro au sort
		int no=(int)(2 * Math.random());
		no = no+1;
		//si on est au premier tour on donne le tour de parole à celui qui à envoyé SABM
		if(cpt==0){
		    no = numeroDepart;
		}
		//on force le tour de parole si on a eu un RNR au tour d'avant
		if(memo.equals("RNR")){
		    no = menExtr;
		    memo="";
		}

		//si c'est 1, c'est l'extrémité 1 qui parle
		if(no == 1){
		    PaquetX25 paquetATraiter1 = (PaquetX25)pourExtremite1.elementAt(indice1);
		    String data1 = paquetATraiter1.getDonnees();
		    //si CA ou CE on regarde s'il y a eu un appel avant en regardant si la vl est bien prise.
		    //si ce n'est pas le cas on va donner la parole à l'autre extrémité pour obtenir l'appel
		    //ce paquet contenant CA ou CE ne sera pas traiter tout de suite mais après l'appel
		    if(data1.equals("CA")||data1.equals("CE")){
			Voie v =  paquetATraiter1.getVL();
			if(v.estLibre()){
			    indice1=indice1;       //on traite le même paquet 
			}
			else{
			    //si 6 trame ss acq la 7ième envoyé devra avoir son bit pf à 1 et le tour de parole est donné à l'autre extrémité
			    if(extremite1.getNbTrameSansAcq() == 6){
				traiteVecteurX25(pourExtremite1, indice1, true);
				indice1++;
				traiteVecteurX25(pourExtremite2, indice2, false);
				indice2++;
			    } //sinon à 0
			    else{
				traiteVecteurX25(pourExtremite1, indice1, false);
				indice1++;
			    }
			}
		    }
		    else{ //si autre que CA ou CE
			if(extremite1.getNbTrameSansAcq() == 6){
			    s3 = paquetATraiter1.getDonnees();
			    s4 = new StringTokenizer(s3,"/");
			    s5 = s4.nextToken();
			    if(s5.equals("RNR")){ //si RNR alors on force le tour de parole suivant
				menExtr=1;
				memo="RNR";
			    }
			    traiteVecteurX25(pourExtremite1, indice1, true);
			    indice1++;
			    traiteVecteurX25(pourExtremite2, indice2, false);
			    indice2++;
			}
			else{
			    s3 = paquetATraiter1.getDonnees();
			    s4 = new StringTokenizer(s3,"/");
			    s5 = s4.nextToken();
			    if(s5.equals("RNR")){
				menExtr=1;
				memo="RNR";
			    }
			    traiteVecteurX25(pourExtremite1, indice1, false);
			    indice1++;
			}
		    }
		}
		else{ //si le tour de parole est à l'extrémité 2, on procède comme pour l'extrémité 1
		    PaquetX25 paquetATraiter2 = (PaquetX25)pourExtremite2.elementAt(indice2);
		    String data2 = paquetATraiter2.getDonnees();
		    //CA ou CE ss appel avant
		    if(data2.equals("CA")||data2.equals("CE")){
			Voie v = paquetATraiter2.getVL();
			if(v.estLibre()){
			    indice2=indice2;
			}
			else{ //sinon on vérifie le nb de trames ss acq
			    if(extremite2.getNbTrameSansAcq() == 6){
				traiteVecteurX25(pourExtremite2, indice2, true);
				indice2++;
				traiteVecteurX25(pourExtremite1, indice1, false);
				indice1++;
			    }
			    else{
				traiteVecteurX25(pourExtremite2, indice2, false);
				indice2++;
			    }
			}
		    }
		    else{ //autre que CA et CE
			if(extremite2.getNbTrameSansAcq() == 6){
			    s3 = paquetATraiter2.getDonnees();
			    s4 = new StringTokenizer(s3,"/");
			    s5 = s4.nextToken();
			    if(s5.equals("RNR")){
				menExtr=2;
				memo="RNR";
			    }
			    traiteVecteurX25(pourExtremite2, indice2, true);
			    indice2++;
			    traiteVecteurX25(pourExtremite1, indice1, false);
			    indice1++;
			}
			else{
			    s3 = paquetATraiter2.getDonnees();
			    s4 = new StringTokenizer(s3,"/");
			    s5 = s4.nextToken();
			    if(s5.equals("RNR")){
				menExtr=2;
				memo="RNR";
			    }
			    traiteVecteurX25(pourExtremite2, indice2, false);
			    indice2++;
			}
		    }
		}
	    }
	    cpt++; //le nombre de paquet traiter
	} //fin du traitement, sortie de la boucle while
	
	fichier2.setText(litFichier(s)); //on écrit le fichier de sortie dans la fenêtre
    }

 /**permet de créer l'interface pour utiliser la simulation : les actions possibles : choix du fichier d'entrée, afichage de ce dernier, démarrage de la simulation, affichage des messages X25 décryptés puis affichage du fichier de sortie (trame HDLC)     */
    public void fenetre(){
	fenetre = new Frame("HDLC Simulator");
	fenetre.addWindowListener(new WindowAdapter(){
		public void windowClosing(WindowEvent e){
		    System.exit(0);
		}
	    }
				  );

	MenuBar mabarre = new MenuBar();
	
	Menu  menuFichier = new Menu("Fichier");
	MenuItem itemAPropos=new MenuItem("A propos");
	itemAPropos.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e){
		    JOptionPane.showMessageDialog(fenetre,"<html><center><b><font color=red>Logiciel HDLC Simulator</font></b><br>Réalisation:<br>Julien Van Den Bossche<br>Benoît Moulin<br>Copyright décembre 2003<br></center></html>");
		}
	    }
				      );
	menuFichier.add(itemAPropos);
	MenuItem itemQuitter=new MenuItem("Quitter");
	itemQuitter.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e){
		    System.exit(0);
		}
	    }
				      );
	menuFichier.add(itemQuitter);
	mabarre.add(menuFichier);

	panel = new JPanel();
	panelHaut = new JPanel();
	panelBas = new JPanel();
	panelCentral = new JPanel();
	panel.setLayout(new BorderLayout());
	panelCentral.setLayout(new BorderLayout());

	panel.add(panelBas,BorderLayout.SOUTH);
	panel.add(panelHaut,BorderLayout.NORTH);
	panel.add(panelCentral,BorderLayout.CENTER);
	panel.setPreferredSize(new Dimension(900, 600));
	panelBas.setPreferredSize(new Dimension(600, 80));
	panelHaut.setPreferredSize(new Dimension(600, 80));
	panelCentral.setPreferredSize(new Dimension(600, 440));
	panelBas.add(label4);
	fenetre.setMenuBar(mabarre);
	fenetre.add(panel);
	champURL = new JTextField(15);
	ImageIcon iconOuvre = new ImageIcon("ouvre.gif");
  	JButton boutonURL = new JButton("Choisir le fichier",iconOuvre);

  	//le file chooser
          final JFileChooser fc = new JFileChooser();
          boutonURL.addActionListener(new ActionListener() {
  		public void actionPerformed(ActionEvent e) {
  		    int returnVal = fc.showOpenDialog(fenetre);
  		    if (returnVal == JFileChooser.APPROVE_OPTION) {
  			File file = fc.getSelectedFile();
  			champURL.setText(file.getAbsolutePath());
			fichier1.setText(litFichier(file.getAbsolutePath()));
  		    } 
  		}
  	    });
	  panelHaut.add(champURL);
	  panelHaut.add(boutonURL);
	  fichier1 = new JTextArea(10,30);
	  fichier2 = new JTextArea(10,30);
	  fichier3 = new JTextArea(10,30);
	  fichier1.setAutoscrolls(true);
	  fichier2.setAutoscrolls(true);
	  fichier3.setAutoscrolls(true);
	  Border blackline = BorderFactory.createLineBorder(Color.black);
	 
	  TitledBorder titre1 = BorderFactory.createTitledBorder(blackline, "Paquets X25 à transmettre");
	  titre1.setTitleJustification(TitledBorder.CENTER);
	 
	  TitledBorder titre2 = BorderFactory.createTitledBorder(blackline, "Interprétation des paquets X25");
	  titre2.setTitleJustification(TitledBorder.CENTER);
	 
	  TitledBorder titre3 = BorderFactory.createTitledBorder(blackline, "Trames HDLC générées");
	  titre3.setTitleJustification(TitledBorder.CENTER);
	  
	  
	  JScrollPane scroll1 = new JScrollPane(fichier1);
	  scroll1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
	  scroll1.setPreferredSize(new Dimension(250, 350));
	  scroll1.setBorder(titre1);
	 
	  JScrollPane scroll2 = new JScrollPane(fichier3);
	  scroll2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
	  scroll2.setPreferredSize(new Dimension(250, 350));
	  scroll2.setBorder(titre2);
	  
	  JScrollPane scroll3 = new JScrollPane(fichier2);
	  scroll3.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
	  scroll3.setPreferredSize(new Dimension(250, 350));
	  scroll3.setBorder(titre3);
	
	  panelCentral.add(scroll1, BorderLayout.WEST);
	  panelCentral.add(scroll3, BorderLayout.EAST);
	  panelCentral.add(scroll2, BorderLayout.CENTER);

	  boutonSimul = new JButton("Simulation !");
	  boutonSimul.addActionListener(new ActionListener() {
		  public void actionPerformed(ActionEvent e) {
		      if(champURL.getText().equals("")){
			 JOptionPane.showMessageDialog(fenetre, "Vous devez choisir l'url du fichier source.");
		      }
		      else{
			  nbSim++;
			  label4.setText("Le fichier de résultats se trouve dans le répertoire courant de l'application et se nomme : resultats"+nbSim+".txt");
			  panelBas.revalidate();
			  fichier3.setText("");
			  creeLiaison(new Liaison());
			  traiteFichier(champURL.getText());
			  boucle();
		      }
		  }
	      }
					);
	  panelHaut.add( boutonSimul);
	  fenetre.setSize(900, 600);
	  fenetre.pack();
	  fenetre.show();
    }
     /**permet de lire un fichier et de mettre son contenu avec le même formatage dans une chaine de caractères
      *@param url l'url du fichier à lire
      */
    public String litFichier(String url){
	String chaine="";
	try{
	    BufferedReader fichier = new BufferedReader(new FileReader(url));
	    String ligne;
	    while((ligne = fichier.readLine()) != null){
		chaine+=ligne+"\n";
	    }
	}
	catch(FileNotFoundException err)
		{
		    System.err.println("Fichier non trouve !\n");
		    System.err.println(err);
		}
	catch(IOException err)
	    {
		    System.err.println("Erreur d'IO\n");
		    System.err.println(err);
	    }
	return chaine;
    } 

    /**affecte une nouvelle liaison pour remplacer l'ancienne liaison de notre précédente simulation.
     *@param l la liaison qui remplace l'ancienne
     */
    public void creeLiaison(Liaison l){
	liaisonHDLC = l;
	vl = l.getVectorVL();
    }

    //le programme principal
    public static void main(String[] args){
	Simulation s = new Simulation();
	s.fenetre();     
    }  
}
