//     $Id: ClientEngine.java,v 3.4 1998/12/10 18:57:23 rgb2u Exp $    
 /////////////////////////////////////////////////////////////////////
 //
 // File: ClientEngine.java
 //
 // Purpose: This describes the Client Engine class.  The Client Engine is
 //          responsible for interfacing between the Client RMI module
 //          and the Client GUI module.  It contains the logic that 
 //          "runs" the client side of the simulation.
 //
 // Authors: rgb  Rob Bartholet  rgb2u@virginia.edu
 //          txe  Travis Emmitt  emmitt@cs.virginia.edu
 // 
 // Modifications:
 //   01-NOV-1998  rgb Initial Creation
 //   02-NOV-1998  rgb Added version control header
 //   02-NOV-1998  rgb Modified to conform to coding standards
 //   04-NOV-1998  rgb Implemented PrintMessage so RMI can write to GUI
 //                rgb Removed rmi.Connect call from ClientEngine constructor
 //                rgb Any calls to rmi methods modified to catch RemoteException
 //   04-NOV-1998  txe Debugging for integration
 //   05-NOV-1998  rgb Updated ReceiveMap() to check state of finalized bit
 //   06-NOV-1998  rgb Trivial change to move gui.Notify()  before ClientRMI instantiation
 //   06-NOV-1998  rgb In constructor, moved gui.Freeze() before ClientRMI instantiation
 //                rgb Changed all gui.Notify() to PrintMessage() 
 //   12-NOV-1998  rgb rgb Tested returned maps to ensure they belong to me
 //                rgb Implemented SetClientID()
 //                rgb Implemented ReceiveStats()
 //   13-NOV-1998  rgb Changed connecting message to SetClientID
 //   16-NOV-1998  rgb Added code to throw exceptions and catch exceptions
 //   17-NOV-1998  rgb Fixed some compilation errors with signatures
 //   18-NOV-1998  txe Improved exception handling
 //   18-NOV-1998  rgb Cleaned up code
 //   03-DEC-1998  rgb Added Quit()
 //                rgb Changed check on received map from final to editable  
 //   08-DEC-1998  rgb Added constructor to take address and port
 //                rgb wrapped ReceiveMap around Connect in new constructor 
 //   09-DEC-1998  rgb Removed deprecated constructor
 //                rgb Added unfreeze to SetClientID
 //
 // Todo:  
 //
 /////////////////////////////////////////////////////////////////////
 import java.rmi.*;
 public class ClientEngine {
   private ClientGUI client_gui; // used to call back ClientGUI
   private ClientRMI client_rmi; // used to communicate with server
   private Map map;              // holds structure and state of model
   private int module_id;        // module number of this workstation
   // constructor
   // ClientEngine instantiated by ClientGui
   // ClientEngine instantiates ClientRMI     
   public ClientEngine (ClientGUI gui, String address, String port) throws Exception {
     if (gui == null) {
       throw new NullException ("gui argument is nulll");
     }
     else {
       client_gui = gui;
       module_id = -1;
       map = null;
       client_gui.Freeze ();// don't allow user to modify the interface
       client_rmi = new ClientRMI (this);
       ReceiveMap (client_rmi.Connect (address, port), -1);
       client_gui.Unfreeze (); // allow user to enter module ID
     }
   }
   // allows client to set his own id
   // subsequently passes id on to RMI
   // if requested id set, returns true
   // if requested id doesn't exist or already taken, returns false
   public boolean SetClientID (int id) throws Exception {
     client_gui.Freeze ();
     PrintMessage ("Attempting to connect to server...");
     module_id = id;
     if (client_rmi.SetClientID (module_id)) {
       PrintMessage ("Connected to server");
       if (map != null && map.IsEditable () ) {
     client_gui.Unfreeze ();
       }
       return (true);
     }
     module_id = -1;
     client_gui.Unfreeze ();
     return (false);
   }
   // receive map from server and send to gui
   public void ReceiveMap (Map my_map, int my_module_id) throws Exception {
     if (my_map == null) {
       throw new NullException ("my_map argument is null");
     }
     else {
       map = my_map;
       if (module_id != my_module_id) {
     throw new EqualityException ("unexpected module_id");
       }
       client_gui.DisplayMap (map, module_id);
       // if map is stabilized
       if ( my_map.IsEditable () ) {
     client_gui.Unfreeze();// allow user to use the interface  
       }
     }
   }
   // receive stats from server and send to gui
   public void ReceiveStats (Stats my_stats, int my_module_id) throws Exception {
     if (my_stats == null) {
       throw new NullException ("my_stats is null");
     }
     else {
       if (module_id != my_module_id) {
     throw new EqualityException ("unexpected module_id");
       }
       client_gui.DisplayStats (my_stats);
     }
   }
   // user clicks on node
   // toggle node and redisplay map
   public void NodeClicked (int my_module_id, int node_id) throws Exception {
     if (my_module_id != module_id) {// not in our module
       PrintMessage ("Can't toggle a node from another module");
     }
     else {
       map.ToggleNode (my_module_id, node_id);
       client_gui.DisplayMap (map, module_id);
     }
   }
   // user done inputting changes
   // send changes to server
   public void DoneClicked () throws Exception {
     Module my_module = null;
     PrintMessage ("Sending changes to server...");
     client_gui.Freeze ();// freeze interface so user can't use it
     my_module = map.GetModule (module_id);
     client_rmi.SendChanges (my_module);
   }
   // RMI wants to print a message to the GUI output
   // receive string from RMI, pass on to GUI
   public void PrintMessage (String s) {
     client_gui.Notify (s);
   }
   // Demon user decides to shut down system
   // freeze display and print shut down message
   public void Shutdown () {
     client_gui.Freeze ();
     PrintMessage ("System shut down by server");
   }
   // Method for RMI to pass exceptions to GUI for display
   public void Error (Exception e) {
     client_gui.Error (e);
   }
   // method for gui to call when applet is destroyed
   public void Quit () throws Exception {
     client_rmi.Quit ();
   }
 }