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

/* Obsluhuje zprávy od klienta.

   Při počátečním připojení:
       reakce na klienta je:
             ok <playerID>   nebo    full
       a druhému klientovi, je-li první přijat:
             added <playerID>

   zprávy pro druhého klienta:
   * disconnect
     zpráva pro druhého klienta:
             removed <playerID>
       
   * try <posn>
     odpověď klientovi
        tooFewPlayers
      zpráva druhému klientovi, je-li tah přijat
        otherTurn <playerID> <posn>
*/

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


public class PlayerServerHandler extends Thread
{
  private FBFServer server;
  private Socket clientSock;
  private BufferedReader in;
  private PrintWriter out;

  private int playerID;     // id tohoto hráče přiřazuje vlákno FBFServer


  public PlayerServerHandler(Socket s, FBFServer serv)
  {
    clientSock = s;
    server = serv;
    System.out.println("Požadavek na připojení hráče");
    try {
      in  = new BufferedReader( 
			    new InputStreamReader( clientSock.getInputStream() ) );
      out = new PrintWriter( clientSock.getOutputStream(), true );  // autoflush
    }
    catch(Exception e)
    {  System.out.println(e);  }
  }


  public void run()
  /* Přidá tohoto hráče do pole objektu typu FSFServer, získá jeho ID a poté
     spustí zpracování vstupu na straně klienta
  */
  {
    playerID = server.addmlayer(this);
    if (playerID != -1) {    // -1 znamená, že hráč byl odmítnut
      sendMessage("ok " + playerID);
      System.out.println("ok " + playerID);  // oznam hráči jeho playerID
      server.tellOther(playerID, "added " + playerID);

      processPlayerInput();

      server.removePlayer(playerID);   // odeber hráče z dat serveru
      server.tellOther(playerID, "removed " + playerID);    // oznam ostatním
    }
    else    // hra je již plná
      sendMessage("full");

    try {     // uzavři socket hráče
      clientSock.close();
      System.out.println("Hráč " + playerID + " uzavřel spojení\n");
    }
    catch(Exception e)
    {  System.out.println(e);  }

  }  // konec metody: run()


   private void processPlayerInput()
   /* Zastav, jakmile se vstupní proud uzavře (je null) nebo je odeslána zpráva "disconnect".
      Jinak předej vstup metodě doRequest(). */
   {
     String line;
     boolean done = false;
     try {
       while (!done) {
         if((line = in.readLine()) == null)
           done = true;
         else {
           // System.out.println("Hráč " + playerID + " zpráva: " + line);
           if (line.trim().equals("disconnect"))
             done = true;
           else 
             doRequest(line);
         }
       }
     }
     catch(IOException e)
     {  System.out.println("Hráč " + playerID + " uzavřel spojení"); }
   }  // konec metody: processPlayerInput()


  private void doRequest(String line)
  /*  Vstupní řádek může obsahovat:
         try <posn>    -- pokus o tah na pozici pos (pos == 0-63)

      Pozice se zde vůbec nekontroluje; předpokládáme, že ji zkontroloval klient
      Pořadí tahů se také nekontroluje; předpokládáme, že to provádí klient
  */
  {
    if (line.startsWith("try")) {
      try {
        int posn = Integer.parseInt( line.substring(4).trim() );
        // System.out.println("Hráč " + playerID + " chce hrát na pozici " + posn);

        if (server.enoughPlayers())
          server.tellOther(playerID, "otherTurn " + playerID + " " + posn);  // předej tah dalším
        else
          sendMessage("tooFewPlayers");
      }
      catch(NumberFormatException e)
      { System.out.println(e); } 
    }
  }  // konec metody: doRequest()


  synchronized public void sendMessage(String msg)
  // volá se obslužným objektem a serverem na nejvyšší úrovni
  { try {
        out.println(msg);
    }
    catch(Exception e)
    {  System.out.println("Obslužné vlákno hráče " + playerID + "\n" + e);  }
  }  // konec metody: sendMessage()


}  // konec třídy: PlayerServerHandler
