import java.io.*;
import java.net.*;
import java.util.*;
import java.util.jar.Attributes.Name;

class User {

  String username;
  String password;

  User(String name, String pw) {
    username = name;
    password = pw;
  }
}

public class MessageServer {

  public static final String CREATE = "CREATE";
  public static final String WRITE = "WRITE";
  public static final String GET = "GET";

  static Hashtable<String, Vector<String>> messageTable;
  static Hashtable<String, String> passwords;

  public static void main(String args[]) throws Exception {
    int port = Integer.parseInt(args[0]);
    ServerSocket serverSocket = new ServerSocket(port);
    System.err.println("MessageServer listening at port " + port);
    messageTable = new Hashtable<String, Vector<String>>();
    passwords = new Hashtable<String, String>();
    while (true) {
      Socket socket = serverSocket.accept();
      PrintStream out = new PrintStream(socket.getOutputStream());
      Scanner scanner = new Scanner(socket.getInputStream());
      System.err.println(
        "Accepted connection from " + socket.getRemoteSocketAddress()
      );
      Thread networkListenThread = new Thread() {
        public void run() {
          while (true) {
            out.print("Your command [CREATE/GET/WRITE]: ");
            if (!scanner.hasNextLine()) {
              break;
            }
            String line = scanner.nextLine().trim();
            if (line.length() == 0) continue;
            if (line.toLowerCase().equals(CREATE.toLowerCase())) {
              out.print("Enter username: ");
              String name = scanner.nextLine().trim();
              if (messageTable.containsKey(name)) {
                out.println("Sorry, this username has already been taken.");
                continue;
              }
              out.print("Enter password: ");
              String password = scanner.nextLine().trim();
              User user = new User(name, password);
              messageTable.put(name, new Vector<String>()); //new user, empty set of messages
              passwords.put(name, password);
              System.err.println("User " + name + " created");
            } // if CREATE
            else if (line.toLowerCase().equals(GET.toLowerCase())) {
              out.print("Enter username: ");
              String name = scanner.nextLine().trim();
              out.print("Enter password: ");
              String password = scanner.nextLine().trim();
              if (
                !passwords.containsKey(name) ||
                !passwords.get(name).equals(password)
              ) {
                out.println("Wrong username or password.");
                continue;
              }
              // now the user has been authenticated
              Vector<String> messages = messageTable.get(name);
              if (messages.size() == 0) {
                out.println("You are no new messages.");
              } else {
                out.println("You have " + messages.size() + " new messages.");
                for (int i = 0; i < messages.size(); i++) {
                  out.println((i + 1) + ". " + messages.get(i));
                }
              }
              messageTable.put(name, new Vector<String>()); // delete all messages
            } // if GET
            else if (line.toLowerCase().equals(WRITE.toLowerCase())) {
              out.print("Enter recipient's username: ");
              String name = scanner.nextLine().trim();
              if (!messageTable.containsKey(name)) {
                out.println("Unknown user: " + name);
                continue;
              } else {
                out.print("Your message: ");
                String message = scanner.nextLine().trim();
                if (message.length() == 0) {
                  out.println("Sorry, empty messages are not allowed.");
                  continue;
                }
                messageTable.get(name).add(message);
              }
            } // if WRITE
            else {
              out.print("Unknown command: " + line);
            }
          } // end while
          System.err.println(
            "Client disconnected: " + socket.getRemoteSocketAddress()
          );
        }
      };
      networkListenThread.start();
    }
  }
}
