package com.roguewave.jchat;
import java.net.*;
import java.io.*;
/**
 * The Connection class.
 * <P>
 * The Connection class adds a layer of abstraction to a socket-pair relationship.
 * There must be two instances of a Connection, one on the server and one on the
 * client.  The setClient() and setServer() methods	are provided to specify whether
 * a particular instance of a Connection is a client or a server.
 * </P>
 *
 * <P>
 * A Connection instantiates a Reader that will notify a Dispatcher implementation when
 * a complete command is received.
 * </P>
 *
 * @see     com.roguewave.jchat.Dispatcher
 * @see     com.roguewave.jchat.Reader
 *
 * @version 1.0  96 April 4
 * @author  Eldon J. Metz
 */
public class Connection {
  private String    	   user_;
  private Reader           reader_ ;
  private DataOutputStream outputStream_ ;
  private DataInputStream  inputStream_ ;
  private Socket           socket_;

  /**
   * Creates a Connection on the specified socket. The specified Dispatcher is
   * notified when a complete command is read from the socket.
   */
  public Connection(Socket aSocket, Dispatcher aDispatcher) {
	socket_ = aSocket;

    try {
	  outputStream_ = new DataOutputStream(aSocket.getOutputStream());
	  inputStream_ = new DataInputStream(aSocket.getInputStream());
	  reader_ =  new Reader(inputStream_, 4, aDispatcher);
    } catch (IOException ioe) {
      System.out.println("connection: " + ioe);
    }
  }

  /**
   * Specify that this instance of the Connection is for the client.  A name
   * representing a user is a required parameter.
   */
  public void setClient(String aUser) {
    user_ = aUser;
	send(user_); // Let the Server side of the Connection know who we are
	startReader();
  }

  /**
   * Specify that this instance of the Connection is for the server.
   */
  public void setServer() {
    user_ = reader_.readData();
    startReader();
  }

  /**
   * Helper method which factors out common code for starting the reader
   * thread for both the Server and Client instances.
   */
  private void startReader() {
    reader_.setPriority(Thread.MAX_PRIORITY / 4);
	reader_.start();
  }

  /**
   * Return the user of this connection.
   *
   * @return   Returns a String representing the user of this connection.
   */
  public String getUser() {
    return user_;
  }

  /**
   * Send an array of strings across the socket.
   */
  public synchronized void send(String[] data) {
	for (int i = 0; i < data.length; i++) {
	  send(data[i]);
	 }
  }

  /**
   * Send a String across the socket.
   */
  public synchronized void send(String data) {
	try {
        outputStream_.writeBytes(data + "\n");
	  } catch (IOException ioe) {
	    System.out.println("Connection: " + ioe);
	}
  }

  /**
   * Safely close the Connection.
   */
  public synchronized void close() {
    reader_.stop();
	try {
	  socket_.close();
	}
	catch (IOException ioe) {
	  System.out.println("Connection: " + ioe);
	}
  }
}
