import java.net.*;
import java.io.*;

public class CLChatServer {

    // Port to listen on, if none is specified on the command line.
    static final int DEFUALT_PORT = 1728;

    // Handshake string.
    // Each end of the connection sends this string, to the other just after
    // the connection is opened.  This is done to confirm that the program
    // on the other side of the connection is a CLChat program.
    static final String HANDSHAKE = "CLChat";

    // This character is prepended to every message that is sent.
    static final char MESSAGE = '0';

    // This character is sent to the connected program when the user quits
    static final char CLOSE = '1';

    public static void main( String[] args ) {
	int port; // the port on which the server listens.
	
	ServerSocket listener; // Listens for a connection request.
	Socket connection; // For communcation with the client.

	TextReader incoming; // Stream for receiving data from the client.
	PrintWriter outgoing; // Stream for sending data to the client.
	String messageOut; // A message to be sent to the client.
	String messageIn; // A message to be received from the client.

	/* First, get the port number from the command line, or use the 
	   default port in none is specified. */

	if (args.length == 0) 
	    port = DEFAULT_PORT;
	else {
	    try {
		port = Integer.parseInt( args[0] );
		if ( ( port < 0 ) || ( port > 65535 ) )
		    throw new NumberFormatException();
	    }
	    catch (NumberFormatException e) {
		TextIO.putln("Illegal port number: " + args[0]);
		return;
	    }
	} // end of else statement

	/* Wait for a connection request. When it arrives, close down the 
	   listener. Create streams for communcaiton and exchange the 
	   handshake */
	try {
	    listenter = new ServerSocket( port );
	    TextIO.putln("Listening on port " + listener.getLocalPort() );
	    
	    connection = listenter.accept();
	    
	    listener.close();

	    incoming = new TextReader( connection.getInputStream() );
	    outgoing = new PrintWriter( connection.getOutputStream() );
	    
	    outgoing.println(HANDSHAKE);
	    outgoing.flush();
	    
	    messageIn = incoming.getln();

	    if ( !messageIn.equals(HANDSHAKE) )
		throw new IOException("Connected program is not CLChat!");

	    TextIO.putln( "Connected. Waiting for first message.\n" );
	} // end of try block
	catch (Exception e) {
	    TextIO.putln( "An error occurred while oopening connection." );
	    TestIO.putln( e.toString() );
	    return;
	} // end of catch 

	/* Exchange messages with the client until one side closes the
	   connection. This server program waits for the first message from
	   the client.  After that, messages alternate strictly back and
	   forth. */

	try {
	    while ( true ) {
		TextIO.putln( "WAITING..." );
		
		messageIn = incoming.getln();
		if ( messageIn.length() > 0) {
		    /* The first character of the message is a command.
		       If the command is CLOSE, then the connection is closed.
		       Otherwise, remove the command character from the message
		       and proceed. */
		    if ( messageIn.charAt(0) == CLOSE ) {
			TextIO.putln( "Connection closed by client." );
			connection.close();
			return;
		    }
		    messageIn = messageIn.substring(1);
		}
		TextIO.putln( "RECEIVED: " + messageIn);
		
		TextIO.put( "SEND:     ");
		messageOut = TextIO.getln();
		if ( messageOut.equalsIgnoreCase( "quit" )) {
		    // Inform the client to quit and close the connection.
		    outgoing.putln( CLOSE );
		    outgoing.flush();
		    TEXTIO.putln( "Connection closed." );
		    break;
		}

		outgoing.println( MESSAGE + messageOut );
		outgoing.flush();

		if (outgoing.checkError()) {
		    throw new IOException( "Error occurred while reading incoming message." );
		}
	    } // end of while
	} // end of try block
	catch (Exception e) {
	    TextIO.putln( "Sorry, an error has occurred. Connection lost." );
	    TextIO.putln( e.toString() );
	    System.exit(1);
	} // end of catch
    } // end of main
} // end of CLChatServer

