package barriere;

import java.io.*;
import java.net.*;
import java.util.*;
import park.borne.Afficheur;
import park.borne.impl.*;

public class Serveur {    
  public static void main(String[] args) {    
    try {
      ServerSocket service = new ServerSocket(5588);
      System.out.println("Service en fonctionnement...");
      while (true) { 
        System.out.println("Attente du client...");
        Socket client = service.accept();
        new Client(client).start();
      }
    }
    catch (IOException ex) {
      System.err.println("Erreur: le service est interrompu...");
    } 
  }  
}

class Client extends Thread {
  private Socket client;
  private String résultat = "OK";
  private String classe, méthode;
  private String[] paramètres = new String[3];
  private Afficheur afficheur;
  private BarriereImpl barrière;
  private ClavierImpl clavier;
  
  public Client(Socket client) {
    try {
      this.client = client;
      afficheur = new Afficheur();
      afficheur.initAfficheur();
      afficheur.affiche(0, 0, "EN SERVICE");
      barrière = new BarriereImpl();
      barrière.init();
      clavier = new ClavierImpl();
      clavier.init();
    } 
    catch (Exception ex) {
      System.err.println("Afficheur en panne");
    }
  }
  
  public void run() {     
    System.out.println("Connexion avec : "+client.getInetAddress().getHostAddress());
    try {
      BufferedReader requête = new BufferedReader(new InputStreamReader(client.getInputStream()));
      PrintWriter réponse = new PrintWriter(client.getOutputStream(), true);
      String commande = null;
      do {
        résultat = "OK";
        commande = requête.readLine();
        System.out.println("Commande = "+ commande);
        découpe(commande);
        analyse();      
        System.out.println("Résultat = "+résultat);
        réponse.println(résultat+'\0');
      }
      while (!commande.equals("fin"));
      client.close();
      System.out.println("Connexion interrompue...");
    } 
    catch (IOException ex) {
      System.err.println("Erreur: communication avec le client incorrecte");
    } 
    catch (Exception ex) {
      System.err.println("Soucis d'analyse de la commande...");
    }
  }

  private void découpe(String commande) {
    StringTokenizer analyseur = new StringTokenizer(commande, ":");
    System.out.println("Nombre de parties dans la commande : "+analyseur.countTokens());
    if (analyseur.hasMoreTokens()) {
      classe = analyseur.nextToken();
      System.out.println("Classe : "+ classe);
    }
    if (analyseur.hasMoreTokens()) {
      méthode = analyseur.nextToken();
      System.out.println("Méthode : "+ méthode);
    }    
    for (int i=0; analyseur.hasMoreTokens(); i++) {
      String paramètre = analyseur.nextToken();
      paramètres[i] = paramètre;
      System.out.println("Paramètre : "+ paramètre);
    }    
  } 

  private void analyse() throws Exception {
    if (classe.equals("Afficheur")) gestionAfficheur();
    else if (classe.equals("Barriere")) gestionBarriere();
    else if (classe.equals("Clavier")) gestionClavier();
  }
  
  private void gestionAfficheur() {
     if (méthode.equals("clear"))
       afficheur.clear();
     else if (méthode.equals("home")) 
       afficheur.home();
     else if (méthode.equals("positionCursor")) {
       int x = Integer.parseInt(paramètres[0]);
       int y = Integer.parseInt(paramètres[1]);
       afficheur.positionCursor(x, y);
     }
     else if (méthode.equals("setCursor")) {
       Boolean actif = Boolean.valueOf(paramètres[0]);
       afficheur.setCursor(actif.booleanValue());
     }
     else if (méthode.equals("afficheMessages")) 
       afficheur.afficheMessages(paramètres[0], paramètres[1]);
     else if (méthode.equals("affiche")) {
       int x = Integer.parseInt(paramètres[0]);
       int y = Integer.parseInt(paramètres[1]);
       afficheur.affiche(x, y, paramètres[2]);         
     }
     else if (méthode.equals("afficheCaractere"))
       afficheur.afficheCaractere(paramètres[0].charAt(0));
  }

  private void gestionBarriere() {
     barrière.actualiseEntrees();
     if (méthode.equals("isBoucleAmont")) 
       résultat = !barrière.isBoucleAmont() ? "entree" : "non";
     else if (méthode.equals("isBoucleAval")) 
       résultat = !barrière.isBoucleAval() ? "sortie" : "non";
     else if (méthode.equals("isInFDCH")) 
       résultat = !barrière.isInFDCH() ? "haut" : "non";
     else if (méthode.equals("isInFDCL")) 
       résultat = !barrière.isInFDCL() ? "bas" : "non";
     else if (méthode.equals("setCommandeSensMontee")) {
       if (barrière.isInFDCH()) {
         barrière.setCommandeSensMontee(true);
         barrière.setCommandeSensDescente(false);
         barrière.setCommandeEnable(true);
         System.out.println("La barriere monte...");
       }
       while (barrière.isInFDCH()) barrière.actualiseEntrees();
       barrière.setCommandeSensMontee(false);
       barrière.setCommandeEnable(false);
       System.out.println("La barrière est en haut...");
       résultat = "haut";
     }
     else if (méthode.equals("setCommandeSensDescente")) {
       if (barrière.isInFDCL()) {
         barrière.setCommandeSensMontee(false);
         barrière.setCommandeSensDescente(true);
         barrière.setCommandeEnable(true);
         System.out.println("La barriere descent...");
       }
       while (barrière.isInFDCL()) barrière.actualiseEntrees();
       barrière.setCommandeSensDescente(false);
       barrière.setCommandeEnable(false);
       System.out.println("La barrière est en bas...");
       résultat = "bas";
     }  
  }

  private void gestionClavier() {
    if (méthode.equals("readClavier"))
       résultat = ""+clavier.readClavier();
    else if (méthode.equals("toucheEnfoncee")) {
       do {
         résultat = ""+clavier.readClavier();
       }
       while (résultat.equals("-1"));
    }
  }
}