package breakout;
import java.io.*;
import java.net.*;

/**
 *
 * A class that connects BOClient and BOServer. 
 * Works with BOServer.java and ClientHandler.java.
 * It implements Runnable.
 *
 * @author  Jennifer Shieh
 * @see		java.lang.Runnable
 * @see		breakout.BOServer
 * @see		breakout.BOClient
 *
 */

public class ClientHandler implements Runnable
{
	/**
	 *	A BOServer
	 */
	private BOServer server;
	
	/**
	 *	the Socket connected to the BOClient
	 */
	private Socket client;

	/**
	 *	A DataInputStream
	 */	
	private DataInputStream dis;
	
	/**
	 *	A DataOutputStream
	 */	
	private DataOutputStream dos;
	
	/**
	 *	A Thread
	 */
	private Thread runner;
	
	/**
	 *	An int to keep track of current number of players
	 */
	private int currentPlayerCount;
		
	/**
	 *	The constructor takes a Socket and a BOServer as parameters.  It creates new DataInputStreams and DataOutputStreams
	 * 	connected to the Socket passed in as an argument.  Equates its field currentPlayerCount to the BOServer's currentPlayerCount.
	 *	Also, creates a new Thread on this Object and starts the Thread running.
	 *
	 *	@param Socket	the Socket through which this ClientHandler is connected to a client
	 *	@param BOServer	the central server through which information is broadcast
	 */
	public ClientHandler(Socket s, BOServer server)
	{
		this.server = server;
		this.client = s;
		try
		{
			this.dis = new DataInputStream( this.client.getInputStream() );
			this.dos = new DataOutputStream( this.client.getOutputStream() );
			this.currentPlayerCount = this.server.currentPlayerCount;
		}
		catch(IOException ioe)
		{
			System.out.println("I caught an IOException in ClientHandler constructor");
		}				
		this.runner = new Thread( this );
		this.runner.start();
		
	}
	
	/**
	 *	Runnable's run() method.  Continuously reads any x and y coordinates being sent by its BOClient, and writes those
	 * 	coordinates to everyone except its BOClient.
	 *	Catches IOException.
	 *
	 *	@see #writeOneInt(int i, ClientHandler ch)
	 *	@see BOServer#writeToAllExcept(int x, int y, ClientHandler ch)
	 *	@see java.io.DataInputStream#readInt()
	 */
	public void run()
	{
		System.out.println("Player count: " + currentPlayerCount);
		if (this.currentPlayerCount == 1)
		{
			/*If currentPlayerCount is one, then send that number to all the ClientHandlers except this one*/
			this.server.writeOne(this.currentPlayerCount, this);
		}
		
		while(true)
		{	
			try
			{					
				int x = this.dis.readInt();
				int y = this.dis.readInt();
				this.server.writeToAllExcept(x, y, this);
				
			}
			catch(IOException ioe)
			{
				System.out.println("I caught an IOException ClientHandler run");
			}
		}		
	}

	/**
	 *	Sends the specified int to the BOClient connected by the DataOutputStream.  Flushes after every write.
	 *
	 *	@param int i  the int which should be sent
	 *
	 *	@see java.io.DataOutputStream#writeInt(int)
	 *	@see java.io.DataOutputStream#flush()
	 *
	 */
	public void send(int i)
	{
		try
		{
			this.dos.writeInt(i);
			this.dos.flush();
		}
		catch(IOException ioe)
		{
			System.out.println("I caught an IOException: ClientHandler write");
		}
	}
	
	/**
	 *	Sends two ints, x and y coordinates, to the BOClient connected by the DataOutputStream.  Flushes after every write.
	 *
	 *	@param int x  the x coordinate to be sent
	 *	@param int y  the y coordinate to be sent	 
	 *
	 *	@see java.io.DataOutputStream#writeInt(int)
	 *	@see java.io.DataOutputStream#flush()
	 *
	 */	
	public void sendCoords(int x, int y)
	{	
		try
		{	
			this.dos.writeInt(x);
			this.dos.writeInt(y);
			this.dos.flush();
			System.out.println("Sending coordinates in CH");
		}
		catch(IOException ioe)
		{
			System.out.println("I caught an IOException ClientHandler sendCoords");
		}		
	}
	
	/**
	 *	Reads one int from the Client.  Returns that int.  Generally, either the x or the y coordinate of the ball.
	 *
	 *	@return i the int read from the DataInputStream
	 *
	 *	@see java.io.DataInputStream#readInt()
	 */		
	public int read()
	{	
		int i = 0;
		try
		{
			/*
			 *i is assigned the value of an int read from the Client
			 */
			i = this.dis.readInt();
		}
		catch(IOException ioe)
		{
			System.out.println("IOException ClientHandler read");
		}		
		return i;
	}
}
