import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

 /** 
  * An applet based RMI chat client
  */
public class ChatApplet  extends Applet {

   String name;
   Client c;
   Server s;
   Connection conn;

   final Color standardButtonColor = Color.red;
   final Color selectedButtonColor = Color.green;

   Hashtable  buttons = new Hashtable();

   String confidential = null;
 TextArea transcript = new TextArea("Transcript:\n", 20, 70, 
	TextArea.SCROLLBARS_VERTICAL_ONLY);

 TextField msg = new TextField(50);

  Button quit = new Button("Quit");

  Panel panel = new Panel();
  Panel whoPanel = new Panel();

  PersonButtonListener pbl = new PersonButtonListener();
  class ChatClientImpl  extends UnicastRemoteObject
        implements Client {

	public ChatClientImpl () throws RemoteException {}
	
        public void whoChanged() throws java.rmi.RemoteException {
		updateWho();
		}
        public void speak(String who, String msg) throws java.rmi.RemoteException
		{
		String o = who + ": " + msg + "\n";
		if (transcript != null) transcript.append(o);
		else System.out.print(o);
		}
	}

  class PersonButtonListener implements ActionListener {
	public void actionPerformed(ActionEvent e) {	
		String s = e.getActionCommand();
		if (confidential != null && confidential.equals(s)) {
			Button b = (Button) buttons.get(confidential);
			if (b != null) 
				b.setBackground(standardButtonColor);
			confidential = null;
			}
		else {
			Button b;
			if (confidential != null) {
			   b = (Button) buttons.get(confidential);
			   if (b != null) b.setBackground(standardButtonColor);
			   }
			confidential = s;
			b = (Button) buttons.get(confidential);
			if (b != null) 
				b.setBackground(selectedButtonColor);
			}
		}
	}
  public ChatApplet(String nm) {
	   name = nm;
	   try {
	     c = new ChatClientImpl();
	     s= (Server)Naming.lookup("//savoir.cs.umd.edu/ChatServer");
		     conn = s.logon(name,c);
	     synchronized(this) {
		     notify();
		     }
	     }
	   catch (Exception e) {
		System.err.println("Error starting applet:" + e);
		c = null;
		s = null;
		conn = null;
		}
	   }

  public void init() {
	BorderLayout layout = new BorderLayout();
	setLayout(layout);
	add("Center",transcript);
	transcript.setEditable(false);
	panel.setLayout(new FlowLayout());
	add("South",panel);
	whoPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
	add("North",whoPanel);
	// add("South",msg);
	panel.add(new Label(name+":"));
	panel.add(msg);
	msg.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {	
			try {
				if (confidential != null) 
					conn.say(confidential,e.getActionCommand());
				else conn.say(e.getActionCommand());
			    }
			catch (Exception err) { System.out.println("Error while saying. error: " + err); }
			msg.setText("");
			}
		});
	// add("East",quit);
	panel.add(quit);
	quit.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {	
			doQuit();
			}
		});
	}

  synchronized void doQuit() {  
      try {
	  conn.logoff();
	  System.exit(0);
	}
      catch (Exception err) { System.out.println("Error while trying to quit. " + err); };
      }

  synchronized void updateWho() {
	while (conn == null) {
		try {
	  	  wait();
		  }
		catch (InterruptedException e) {
			System.out.println("Interrupted?? " + e);
			}
		}
	whoPanel.removeAll();
	try {
	    String[] w = conn.who();
	    for(int i = 0; i < w.length; i++)  {
		if (!w[i].equals(name))  {
			Button b = (Button) buttons.get(w[i]);
			if (b == null) {
				b = new Button(w[i]);
				b.setBackground(standardButtonColor);
				b.addActionListener(pbl);
				buttons.put(w[i],b);
				};
			whoPanel.add(b);
			}
	    }
	  }
      catch (Exception err) { 
		System.out.println("Error while updating who. " + err); 
		err.printStackTrace(System.out);
		};
	whoPanel.setSize(whoPanel.getPreferredSize());
        whoPanel.validate(); 
	validate();
	}

  public static void main(String[] args) throws Exception {
	   
	   final ChatApplet applet = new ChatApplet(args[0]); 
	   if (applet.conn == null) return;
	    Frame aFrame = new Frame("Chat Client for " + args[0]);
	    aFrame.addWindowListener(
	      new WindowAdapter() {
		public void windowClosing(WindowEvent e) {
		  applet.doQuit();
		  }
	      });
	    aFrame.add(applet, BorderLayout.CENTER);
	    applet.setVisible(true);
	    applet.validate();
	    
	    applet.validate();
	    aFrame.validate();
	    applet.init();
	    aFrame.setVisible(true);
	    aFrame.pack();
	    applet.start();
	    // aFrame.setSize(700,400);
  }
}
