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

public class AquaServer {
	static Vector clientList= new Vector();
	static PrintWriter screenOut = new PrintWriter(System.out, true);
	static ServerSocket serverSocket = null;

	public static void main(String[] args) throws IOException {
		
		boolean listening = true;
		CommandReader tempCommand;
		Thread tempThread;
		AquaClientThread tempClient;
		int currentNode;
		screenOut.println("A|Q|U|A Server v1.5");
		screenOut.println(" Copyright 2000 by Branden J. Hall of Fig Leaf Software");
		screenOut.println(" http://www.figleaf.com | bhall@figleaf.com");
		screenOut.println("------------------------------------------------------");
		screenOut.println(" Authors notes:");
		screenOut.println("  The server now supports commands. Type HELP to see the");
		screenOut.println("  list of supported commands. Thanks to Dave Watts, ");
		screenOut.println("  Kurt Hakenson, Patti Lee, and the rest of the ");
		screenOut.println("  Notorius F.I.G.");
		screenOut.println("------------------------------------------------------");
		if  (args.length >= 1){
			Integer tempPort = new Integer(args[0]);
			try{
				serverSocket = new ServerSocket(tempPort.intValue());
			}catch(IOException e){
				System.err.println("Could not listen on port: "+args[0]);
				System.exit(-1);
			}
				screenOut.println("Server started and listening on port "+args[0]+"\n");
				screenOut.print(">");
				screenOut.flush();
				tempCommand = new CommandReader();
				tempCommand.start();
			while (listening){
				try{
					tempClient = new AquaClientThread(serverSocket.accept());
					clientList.add(tempClient);
					tempThread = new Thread(tempClient);
					tempThread.start();	
				}
				catch (IOException e){
				}
			}
			serverSocket.close();
		}else{
			screenOut.println("Error: incorrect number of arguments");
			screenOut.println("usage: java AquaServer <port>");
			screenOut.println("Where <port> is an unused port greater than 1024 that the");
			screenOut.println("server will listen on.");
			System.exit(-1);
		}
	}
	
	static void sendToAllClients(String message){
		int i;
		AquaClientThread foo;
		AquaClientThread tempClient;
		for (i=0;i<clientList.size();++i){
			foo = (AquaClientThread)clientList.get(i);
			foo.send(message);
		} 	
	}

	static void listClients(){
		int i;
		AquaClientThread foo;
		for (i=0;i<clientList.size();++i){
			foo = (AquaClientThread)clientList.get(i);
			screenOut.println(" Client "+(i+1)+": "+foo.clientIP);
		} 	
	}
	
	static void deleteClient(AquaClientThread deadClient){
		int num;
		num=clientList.indexOf(deadClient);
		clientList.remove(num);
	}
}

class CommandReader extends Thread{
	BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	PrintWriter screenOut = new PrintWriter(System.out, true);
	String command;
	
	public CommandReader(){
		super("CommandReader");
	}

	public void run(){
		boolean valid;
		try{
			while ((command = in.readLine()) != null){
				valid = false;
				command = command.trim().toUpperCase();
				if (command.compareTo("QUIT")==0){
					valid = true;
					AquaServer.serverSocket.close();
					System.exit(0);
				}
				if (command.compareTo("LIST")==0){
					valid = true;
					screenOut.println("");
					AquaServer.listClients();
					screenOut.println("");
				}
				if (command.compareTo("HELP")==0){
					valid = true;
					screenOut.println("\n LIST - lists all currently connected clients");
					screenOut.println(" QUIT - disconnects all clients and exits\n");
				}
				if (!valid){
					screenOut.println("\nError: Not a supported command\n");
				}
				screenOut.print(">");
				screenOut.flush();
			}
		}
		catch (IOException e){
			e.printStackTrace();
		}
		
	}
};

class AquaClientThread extends Thread {
	PrintWriter screenOut = new PrintWriter(System.out, true);
	private Socket socket = null;
	public String clientIP;
	public PrintWriter out;
	public BufferedReader in;

	public AquaClientThread(Socket socket){
		super("AquaClientThread");
		this.socket = socket;
	}
	
	public void run(){
		clientIP = socket.getInetAddress().getHostAddress();
		try{
			out = new PrintWriter(socket.getOutputStream(), true);
			in = new BufferedReader (new InputStreamReader(socket.getInputStream()));
			String inputLine;
			int streamResult;
			char buf[] = new char[1];
			do{
				inputLine = "";
				do{
					streamResult = in.read(buf, 0, 1);
					inputLine += buf[0];
				} while (buf[0] != '\u0000');
				AquaServer.sendToAllClients(inputLine);
			} while (streamResult != -1);
			AquaServer.deleteClient(this);
			in.close();
			out.close();
			socket.close();
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	
	public void send(String message){
		out.println(message);
	}
}