import java.net.*;
import java.io.*;

/**
 * Client program with object streams
 * This client connects to a server
 * and sends requests to the server
 * This illustrates Object streams and simple
 * Client/Server connections. It's not meant to be
 * a realistic client/server program nor to be
 * a good example of OO design.
 *
 * @author Owen Astrachan
 *
 */
public class Client
{
    private ObjectOutputStream myServerOut;   // stream to server
    private ObjectInputStream  myServerIn;    // stream from server

    private BufferedReader stdIn;             // standard input stream
    private PrintWriter    stdOut;            // standard output stream
    
    public Client()
    {
        // no state to initialize or stdIn/stdOut?
    }

    public void connect(String host, int port)
    {
        Socket sock = null;
        try{
            sock = new Socket(host,port);
        }
        catch(Exception e){
            Debug.println("Server connect error "+e);
        }
        try{
            Debug.println("server connection made");

            // must open input and output from client in
            // different order from server, or we can get
            // some kind of deadlock -- here we do output/then input

            // server output
            myServerOut = new ObjectOutputStream(sock.getOutputStream());
            myServerIn = new ObjectInputStream(sock.getInputStream());

            stdIn = new BufferedReader(new InputStreamReader(System.in));
            stdOut = new PrintWriter(System.out,true);
        }
        catch (Exception e){
            Debug.println("Error client side on connection "+e);
        }
    }

    private void sendGet()
    {
        try{
            stdOut.print("name ");
            stdOut.flush();
            String s = stdIn.readLine();
            myServerOut.writeObject(Globals.GET);
            myServerOut.writeObject(s);
        
            Person p = (Person) myServerIn.readObject();
            if (p == null)
            {
                stdOut.println("no such person");
            }
            else
            {
                stdOut.println(p);
            }               
        }
        catch (IOException e) {
            Debug.println("IO trouble in sendGet "+e);
        }
        catch (ClassNotFoundException cnfe) {
            Debug.println("class/object problem " + cnfe);
        }
    }

    private void sendPut()
    {
        try{
            stdOut.print("name ");
            stdOut.flush();
            String s = stdIn.readLine();
        
            stdOut.print("age ");
            stdOut.flush();
            String age = stdIn.readLine();
        
            myServerOut.writeObject(Globals.PUT);
            myServerOut.writeObject(s);
            myServerOut.writeObject(new Person(s, Integer.parseInt(age)));
        }
        catch (Exception e) {
            Debug.println("trouble in sendGet "+e);
        }
    }

    private void sendQuit()
    {
        try {
            myServerOut.writeObject(Globals.QUIT);
            stdOut.println("client finished");
            
            // we finished, close stream to server          
            myServerOut.close();
        }
        catch (IOException e) {
            Debug.println("trouble quitting " + e);
        }
    }
    
    private void sendGarbage(String s)
    {
        try {
            myServerOut.writeObject(s);
        }
        catch (IOException e) {
            Debug.println("trouble quitting " + e);
        }       
    }

    /**
     * Send messages to server until user says to quit
     *
     */
    public void run()
    {
        while (true) {
            stdOut.print(Globals.GET+":"+Globals.PUT+":"+
                         Globals.QUIT+"> ");
            stdOut.flush();
                
            // get response from user, one line at a time
            String s = null;
            try {
                s = stdIn.readLine();           
            }
            catch (IOException e) {
                Debug.println("I/O problem on client " + e);
            }

            if (s == null) {
                stdOut.println("client finished");
                break;
            }
            else if (s.equals(Globals.PUT)) {
                sendPut();
            }
            else if (s.equals(Globals.GET)) {
                sendGet();
            }
            else if (s.equals(Globals.QUIT)) {
                sendQuit();
                break;
            }
            else {
                sendGarbage(s);
            }
        }
    }
    
    public static void main(String args[])
    {
        Client c = new Client();
        c.connect(Globals.HOST, Globals.PORT);
        c.run();
    }
}
