
// ScoreUDPServer.java
// Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th

/* Server na bázi protokolu UDP uchovávající skóre (a jméno)
   klienta v seznamu 10 nejvyšších bodů.

   Server umí mezi klienty přepínat, protože zpráva každého klienta
   je soběstačná.

   Rozumí vstupní zprávě ve tvaru:
		get					   -- vrací seznam nejvyšších skóre
        score name & score &   -- přidá skóre pro dané jméno
        zpráva bye není třeba, neboť neexistuje žádné dlouhodobé spojení s klientem

   Seznam udržuje v souboru SCORFN a při startu jej načítá.
   Server lze ukončit kombinací klávec CTRL a C.
*/

import java.io.*;
import java.net.*;
import java.util.*;


public class ScoreUDPServer
{
  private static final int PORT = 1234;
  private static final int BUFSIZE = 1024;   // max. velikost zprávy

  private HighScores hs;
  private DatagramSocket serverSock;

  
  public ScoreUDPServer()
  {
    try {  // zkus pro daný server vytvořit socket
      serverSock = new DatagramSocket(PORT);
    }
    catch(SocketException se)
    {  System.out.println(se);
       System.exit(1);
    }

    waitForPackets();
  }  // konec metody: ScoreUDPServer()


  // ------------------------------
  // zpracování požadavků klienta

  
  private void waitForPackets()
  /* Opakovaně přijmi a zpracuj paket a případně odešli odpověď. */
  {
    DatagramPacket receivePacket;
    byte data[];

    hs = new HighScores();

    try {
      while (true) {
        // připrav prázdný paket
        data = new byte[BUFSIZE];
        receivePacket = new DatagramPacket(data, data.length);

        System.out.println("Čekám na paket ...");
        serverSock.receive( receivePacket );

        processClient(receivePacket);
 
        hs.saveScores();      // zálohuj tabulku s nejvyšším počtem bodů po dokončení každého paketu
      }
    }
    catch(IOException ioe)
    {  System.out.println(ioe);  }
  }  // konec metody: waitForPackets()



   private void processClient(DatagramPacket receivePacket)
   // extrahuj údaje o klientovi z příchozího paketu
   {
      InetAddress clientAddr = receivePacket.getAddress();
      int clientPort = receivePacket.getPort();
      String clientMesg = new String( receivePacket.getData(), 0,
                           receivePacket.getLength() );

      System.out.println("Pakte od klienta " + clientAddr +
                                          ", " + clientPort );
      System.out.println("Zpráva klienta: " + clientMesg);
        
      doRequest(clientAddr, clientPort, clientMesg);
   }  // konec metody: processClient()


  private void doRequest(InetAddress clientAddr, int clientPort, String clientMesg)
  /*  Vstupní řádek může vypadat buď takto:
             "score name & score &"
      nebo takto:
            "get"
  */
  {
    if (clientMesg.trim().toLowerCase().equals("get")) {
      System.out.println("Zpracovávám 'get'");
      sendMessage(clientAddr, clientPort, hs.toString() );
    }
    else if ((clientMesg.length() >= 6) &&     // "score "
        (clientMesg.substring(0,5).toLowerCase().equals("score"))) {
      System.out.println("Zpracovávám 'score'");
      hs.addScore( clientMesg.substring(5) );    // odřízni klíčové slovo score
    }
    else
      System.out.println("Ignoruji vstupní řádek");
  }  // konec metody: doRequest()


  private void sendMessage(InetAddress clientAddr, int clientPort, String mesg)
  // pošli zprávu socketu na specifikovanou adresu a port
  {
    byte mesgData[] = mesg.getBytes();   // převeď zprávu na pole bajtů
    try {
      DatagramPacket sendmacket =
          new DatagramPacket( mesgData, mesgData.length, clientAddr, clientPort);
      serverSock.send( sendmacket );
    }
    catch(IOException ioe)
    {  System.out.println(ioe);  }
  }  // konec metody: sendMessage()


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

  public static void main(String args[]) 
  {  new ScoreUDPServer();  }

} // konec třídy: ScoreUDPServer

