package client;

import java.rmi.*;
import server.ServerInterface;
import javax.swing.*;
import java.awt.*;

/****
 *
 * Class Client is a simple illustration of a client that communicates with a
 * remote server using RMI.  The client provides server-setup and computation
 * methods, detailed descriptions of which are given in the method
 * documentation.
 *									    <p>
 * The <tt>main</tt> method of the client accepts two command-line arguments.
 * The first argument is the name of the host on which the server is running.
 * The host name may be suffixed with a colon-delimited port number.  If the
 * port number is not present, the rmiregistry on the remote host is assumed to
 * be running on the well-known port 1099.  So, e.g., a legal hostname could be
 * "waldorf.csc.calpoly.edu" or "waldorf.csc.calpoly.edu:1098", the latter
 * selecting alternate registry port 1098.
 *									    <p>
 * The second command-line argument is an optional flag indicating if the
 * client's GUI should be displayed when it runs.  If the argument is missing,
 * the default behavior is to display the GUI.  If the second argument is
 * "<tt>-nd</tt>", then no GUI display is shown.  Using the "-nd" argument is
 * useful when the client is run in a context where there is no support for a
 * Java GUI display, for example, running the client on a UNIX machine like
 * waldorf when logged into waldorf via telnet from a Windows PC.
 *									    <p>
 * See the <a href= ../server/Server.html> Server </a> class for a description
 * of the server that this client uses.
 *
 */
public class Client {

    /**
     * Establish communication with the server running on the given
     * <tt>hostname</tt>.  As explained in the class documentation, the
     * hostname may be suffixed with colon-delimited port number.  The hostname
     * is used to create a server name of the form
     * "<tt>//<em>hostname</em>/Server</tt>".  See the documentation for the <a
     * href="../server/Server.html#setupServer(java.lang.String)">
     * <tt>server.Server.setupServer</tt> </a> method for a explanation of this
     * server-name syntax.
     */
     protected static void establishCommunication(String hostname) {

	/*
	 * Set up the security manager if necessary.
	 */
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }

	/*
	 * Establish communication with the server.
	 */
        try {
            server = (ServerInterface) Naming.lookup(
		"//" + hostname + "/Server");
        }
	/*
	 * Handle any remote exception that may occur during server set up or
	 * execution.
	 */
        catch (Exception e) {
            System.err.println("Server exception: " +  e.getMessage());
            e.printStackTrace();
        }

    }

    /**
     * Set up the display as a JFrame with a labeled text field.  The
     * </tt>hostname</tt> input is the command-line argument from main.
     */
    protected static void setupDisplay(String hostname) {

	/*
	 * Allocate the frame and its innards.
	 */
	JFrame frame = new JFrame();
	JPanel panel = new JPanel();
	Box box = Box.createHorizontalBox();

	/*
	 * Add the text field.
	 */
	textField = new JTextField(8);
	box.add(new JLabel("Result of server computation: "));
	box.add(textField);

	/*
	 * Add border for some spacing.
	 */
	panel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
	panel.add(box, BorderLayout.CENTER);

	/*
	 * Add to, pack, and make visible the frame.
	 */
	frame.setTitle("Client of " + hostname);
	frame.getContentPane().add(panel);
	frame.pack();
	frame.setVisible(true);
    }

    /**
     * Call the following methods on the remote server:
     *							              <ol> <li>
     *	   <a href= ../server/Server.html#receiveClientInput(client.ClientDataInterface)>
     *	   <tt>receiveClientInput</tt> </a>
     *									   <li>
     *	   <a href= ../server/Server.html#compute()>
     *	   <tt>compute</tt> </a>
     *									   <li>
     *	   <a href= ../server/Server.html#getServerOutput()>
     *	   <tt>getServerOutput</tt> </a>
     *								          </ol>
     *
     * Display the resulting server output in the display window, or write the
     * output to stdout if the display is not on.  The actual computation is
     * very simple -- a client data value of 10 is sent to the server, to which
     * the server simply adds 1, resulting in an output of 11.
     */
    protected static void performComputation() {

	/*
	 * Call server methods to send data, perform computation, and get back
	 * results.
	 */
	try {
            server.receiveClientInput(new ClientData(10));
            server.compute();
	    if (displayOn) {
		textField.setText(server.getServerOutput().toString());
	    }
	    else {
		System.out.println("Result of server computation: " +
		    server.getServerOutput());
	    }
	}
	/*
	 * Handle any remote exception that may occur during server execution.
	 */
        catch (Exception e) {
            System.err.println("Server exception: " + e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * Get the hostname from command-line argument, exiting if there is none.
     * Then call the methods to establish communication with server and perform
     * the simple computation.
     */
    public static void main(String args[]) {

	/*
	 * Make sure there's a hostname given on the command line.
	 */
	if (args.length == 0) {
	    System.out.println(
		"First command-line argument must be a host name.");
	    System.exit(0);
	}

	/*
	 * Set up the display if the second command-line arg is != "-nd".
	 */	
	if ((args.length > 1) && (args[1].equals("-nd"))) {
	    displayOn = false;
	}
	else {
	    displayOn = true;
	    setupDisplay(args[0]);
	}

	/*
	 * Establish communication and compute.
	 */	
	establishCommunication(args[0]);
	performComputation();

    }


    /** The remote server class; note the use of the interface type in the
        declaration, which means that the server implementation need not be
        (and typically is not) on the client machine. */
    protected static ServerInterface server;

    /** The text field that displays the result computed by the server; the
        result is printed to stdout instead of this text field if the GUI
        display is not active */
    protected static JTextField textField;

    /** True if the display is on, i.e., the 2nd command-line arg != "-nd" */
    protected static boolean displayOn;

}