// TalkApplet.java
//
// This program is created by modifying an example from the book 
// _Java in a Nutshell_ by David Flanagan. You may study, use, modify, 
// and distribute this example for any purpose. This program is 
// provided WITHOUT WARRANTY either expressed or implied.
//
// (C) Henrik Björkman 1997
//
// This applet will connect to a port on a server and open
// a window with one field for input from keyboard and one
// field for output received from the server.
//
// History:
// 0.0 Created by Henrik Björkman 1997-05-03

import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;

public class TalkApplet extends Applet 
{
  public static final int PORT = 6789;
  TalkClient client;

  // Just for debugging.
  static void debug(String s)
  {
    //System.out.println("TalkApplet: " + s);   
  }

    
  public void init() 
  {
    String hostname=this.getCodeBase().getHost();
    client=new TalkClient(this,hostname,PORT);
  }


  public void destroy()
  {
    debug("destroy"); 
    client.term();
    client=null;
    this.stop();
    this.hide();
    //this.dispose();
  }

  public boolean action(Event e, Object arg)
  {
    return(client.handleEvent(e));
  }


}



class TalkClient
{
  public static final int DEFAULT_PORT = 5000;

  Socket s = null;
  int port = DEFAULT_PORT;
  String hostname;
  Container container;
  DataInputStream in;
  PrintStream out;
  TextField inputfield;
  TextArea outputarea;
  TalkListener listener;

  static int exit_count=1; // Do system exit if this reaches zero.
  int event_count=0; // Just for debugging

  public TalkClient(Container container, String hostname, int port)
  {
    try 
    {
      // Create a socket to communicate to the specified host and port
      s = new Socket(hostname, port);

      // Create streams for reading and writing lines of text
      // from and to this socket.
      in = new DataInputStream(s.getInputStream());
      out = new PrintStream(s.getOutputStream());
            
      // Tell the user that we've connected
      System.out.println("HClient: Connected to " + s.getInetAddress()
          + ":"+ s.getPort());


      this.container=container;
      inputfield = new TextField();
      outputarea = new TextArea();
      outputarea.setEditable(false);
      container.setLayout(new BorderLayout());
      container.add("South", inputfield);
      container.add("Center", outputarea);

      listener = new TalkListener(in, outputarea);


      // container.pack();
      container.show();

    }      
    catch (IOException e) 
    {
      System.err.println(e); 
    }
    finally 
    {
      // Always be sure to close the socket if any
      //try { if (s != null) s.close(); } catch (IOException e2) { ; }
    }

  }


  // Just for debugging.
  static void debug(String s)
  {
    //System.out.println("TalkClient: " + s);   
  }


  // This will handle all events.
  public boolean handleEvent(Event e) 
  {
    debug("handleEvent "+(event_count++));

    switch(e.id)
    {
      case Event.ACTION_EVENT:
      {
        if (e.target == inputfield) 
        {
          debug("inputfield");
          String str=inputfield.getText();
          debug("str "+str);
          out.println(str);
          inputfield.setText("");
          return true;
        }
        break;
      }
      default:
      {
        debug("Other event");
        break;
      }
    }
    return false;
  }

  public void term()
  {
    debug("TalkClient: term");

    listener.stop();
    listener=null;
    inputfield.hide();
    inputfield=null;
    outputarea.hide();
    outputarea=null;

    try { s.close(); } catch (IOException e2) { ; }
  }



  public void finalize()
  {
    System.out.println("TalkClient: finalize");

    try { if (s != null) s.close(); } catch (IOException e2) { ; }
  }



} // End of class



// Wait for output from the server on the specified stream, and display
// it in the specified TextArea.
class TalkListener extends Thread 
{
  DataInputStream in;
  TextArea output;

  // Just for debugging.
  static void debug(String s)
  {
    //System.out.println("TalkListner: " + s);   
  }

  public TalkListener(DataInputStream in, TextArea output) 
  {
    this.in = in;
    this.output = output;
    this.start();
    debug("start");
    //output.appendText("testing...\n");
  }

  public void run() 
  {
    String line;
    try 
    {
      for(;;) 
      {
        line = in.readLine();
        if (line == null) break;
        output.appendText(line+"\r\n");
      }
    }
    catch (IOException e) { output.appendText(e.toString()+"\r\n"); }
    finally { output.appendText("Connection closed by server."+"\r\n"); }
  }
}



