//   Course Number: COSC 650 Data Comm/Networks
//      Class Name: ClientConnection.java
//         Authors: Brian Hoffman
//                  Derek Waby
//                  Kypros Ioannou
//                  Harsha V. Reddy
//     Description: The purpose of this class is to encapsulate all of the 
//                  information about a client's connection to the server. 
//                  It accepts the addess and port number of the server in 
//                  its constructor and actually forms the connection upon
//                  calling the connect method. The connect method also sets
//                  up an ObjectInputStream and ObjectOutputStream for use 
//                  by the client. Once setup, a user can make use of the 
//                  provided get methods to obtain access to the socket or 
//                  IO streams. One can also make use of the class's readObject 
//                  and sendObject methods to simplify communication. Finally,
//                  the class contains a close method for terminating the 
//                  connection and properly closing the streams.

// Java Core Packages
import java.io.*;
import java.net.*;

public class ClientConnection
{ 
    private Socket connection;
    private String serverAddress;
    private int portNum;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    
    /**
     * ------------------------------------------------------------------------
     * constructor - gets the server address and port number
     * ------------------------------------------------------------------------
     */
    public ClientConnection(String server, int pNumber)
    {
        serverAddress = server;
        portNum = pNumber;
    }
    
    /**
     * ------------------------------------------------------------------------
     * connect - creates the actual socket connection. Returns true if successful 
     *           and false otherwise
     * ------------------------------------------------------------------------
     */ 
    public boolean connect()
    {
        try
        {
            connection = new Socket(InetAddress.getByName(serverAddress), portNum);
            
            // get the input and output streams and flush header from output
            output = new ObjectOutputStream(connection.getOutputStream());
            output.flush();
            input = new ObjectInputStream(connection.getInputStream());
                
            return true;
        }        
        catch(IOException ioException)
        {
            ioException.printStackTrace();
            return false;
        }
    }
    
    /* ------------------------------------------------------------------------
     * getMethods
     *-------------------------------------------------------------------------
     */
    public String getServerAddress() {return serverAddress; }
    public int getPortNum() {return portNum; }
    public Socket getSocket() { return connection; }
    public ObjectOutputStream getObjOutput() { return output; } 
    public ObjectInputStream getObjInput() { return input; }
    
    /**
     * ------------------------------------------------------------------------
     * sendObject - sends an object on the ObjectOutputStream
     * ------------------------------------------------------------------------
     */
    public void sendObject(Object msg) throws IOException
    {
        output.writeObject(msg);
    }
    
    /**
     * ------------------------------------------------------------------------
     * readObject - reads an object off the ObjectInputStream
     * ------------------------------------------------------------------------
     */
    public Object readObject() throws IOException, ClassNotFoundException
    {
        return input.readObject();
    }
    
    /**
     * ------------------------------------------------------------------------
     * close - closes the connection and catches any errors
     * ------------------------------------------------------------------------
     */
    public void close()
    {
        try
        {
            output.close();
            input.close();
            connection.close();
        }
        catch(IOException ioException)
        {
            ioException.printStackTrace();
        }   
    }
}