
// ChatServer.java
// Andrew Davison, ad@coe.psu.ac.th, May 2023

/* The server runs a 'lobby' space where a user can place a
   ("enter", <user ID>, <room ID>) tuple to request to join 
   the chatroom called roomID. If the room exists, the user is
   sent its URI, If the chatroom doesn't yet exist, then one
   is created.

   The server notifies the user by adding a tuple:
      ("roomURI", <user ID>, <room ID>, roomURI)
   to the lobby. The user will read the roomURI and use it to 
   access the remote space.

  Explained in sections 3.5 and 3.6 at:
    https://github.com/pSpaces/Programming-with-Spaces/blob/master/tutorial-distributed-programming.md

  Usage:
    > compile.bat ChatServer.java
    > run.bat ChatServer

    Part of the application made up of:
       * ChatServer.java
       * ChatClient.java
       * RoomReader.java
            -- this class is not in the original examples
*/

import java.util.*;

import org.jspace.*;


public class ChatServer
{
  private final static String GATE_URI = 
                  "tcp://127.0.0.1:9001/?keep";

  private final static String REMOTE_URI = 
                  "tcp://127.0.0.1:9001/lobby?keep";
     // make sure the space name matches that in SpaceRepository.add();
     // this address will be used by clients of this server

  private final static String CHAT_ADDR =
                            "tcp://127.0.0.1:9001/chat";
    /* partial URI for a new chatroom; a roomCounter integer
       is added to make a unique URI */


  public static void main(String[] args)
  {
    HashMap<String,Integer> roomNums = new HashMap<>();
      // maps <chatroom name/ID> to the roomCounter 
      // integer used in the chatroom URIs

    try {
      SpaceRepository repository = new SpaceRepository();
      repository.addGate(GATE_URI);
      SequentialSpace lobby = new SequentialSpace();
      repository.add("lobby", lobby);

      System.out.println("Opening chat lobby at " + REMOTE_URI);

      // serve requests to enter a specific chatroom
      while (true) {
        int roomCounter = 0;
              // used to ensure every chatroom has a unique name
        String roomURI;

        while (true) {
          Object[] request = lobby.get( 
                        new ActualField("enter"),
                        new FormalField(String.class),   // user ID
                        new FormalField(String.class));  // room ID
          String userID = (String) request[1];
          String roomID = (String) request[2];
          System.out.println(userID + " wants to enter chatroom " + roomID);

          // look up the supplied room name/ID
          Integer roomNum = roomNums.get(roomID);
          if (roomNum != null)
            // if room exists, respond with its URI
            roomURI = CHAT_ADDR + roomNum + "?keep";
          else {
            // if chatroom does not exist, create a new space
            roomURI = CHAT_ADDR + roomCounter + "?keep";
            Space chatSpace = new SequentialSpace();   // the new chatroom
            repository.add("chat"+roomCounter, chatSpace);

            roomNums.put(roomID, roomCounter);  // store new room info
            roomCounter++;
          }

          lobby.put("roomURI", userID, roomID, roomURI);
          System.out.println("Told " + userID + " to enter room " + 
                                              roomID + " at " + roomURI);
        }
      }
    }
    catch (Exception e) 
    {  System.out.println(e);  }
  } /* main */

}  // end of ChatServer class



