/*
Dexter Travis
Bradley University
2001/2002 Senior Project Botdock
http://pioneer1.bradley.edu
http://cegt201.bradley.edu/projects/proj2002/botdock/
*/

import java.io.*;
import java.net.*;
import java.lang.*;
import java.util.*;

//process a new client connection (some one just logged on)
	class ServiceClient implements Runnable
	{
		
		private static final int maxusers = 3;//should be same as above maxusers
		private static ServiceClient clientarray[]=new ServiceClient[maxusers];//array of clients who are connected
		
		//miniloop to initialize all possible clients
		static 	{
			int c;
			for (c=0; c<maxusers; c++) clientarray[c]=null;
			}
		
		//send message to all clients
		static void sendtoall(String msg)
		{
			//miniloop sends message to each client one at a time
			int c;
			for (c=0; c<maxusers; c++)
			if  (clientarray[c] != null)
			clientarray[c].send(msg);
		}	
		
		//disconnect all clients
		static void KillAll()
		{
			int c;
		
			for (c=0; c<maxusers; c++)
			if (clientarray[c] != null) 
			{
				try
				{
					(clientarray[c].SO).close();
					log.log("S killed client # " +c);
				}
				
				catch (Exception e)
				{
					log.log("S error trying to kill client # " +c);
				}
			}
		}
		
		
		//variables and buffers needed for network communications
		private int 	CO=0;
		private Socket 	SO=null;
		private BufferedReader	SocketRead=null;
		private PrintWriter	SocketWrite=null;
		private String		clientaddress="";
		 
		ServiceClient(Socket client)//actually starts new thread for clients
		{
			SO=client;
			//search for empty entry and give CO # (lowest available) to this client
			for (CO=0; CO<maxusers; CO++)
			{
				if (clientarray[CO]==null)break;
			}
			if(CO>maxusers || BatteryDetector.batterygood==false) CO=-1;//if too many users then disconnect this bum
			else clientarray[CO]=this;
			(new Thread(this, "Serving a Client")).start();//starts the thread.
		}
		
		private void send(String msg)
		{
			synchronized (SocketWrite)
			{
				try
				{
					SocketWrite.println(msg);//puts msg in buffer
					SocketWrite.flush();//must flush to empty buffer and physically send
				}
				catch (Exception e)
				{
					try
					{
						SO.close();//if unable to send then they disconnected close connection
						log.log("S user# " +CO+ " disconnected");
					}
					catch (Exception f)
					{
						log.log("E unable to close socket for user# " +CO);
					}
				}
			}
		}
		//is called automatically when new threads are started.
		public void run()
		{
			try
			{
				//store clients IP address as a string
				clientaddress = (SO.getInetAddress()).toString();
				
				//create a stream for reading from client
				SocketRead= new BufferedReader(new InputStreamReader(SO.getInputStream()));
				//create a stream for writing to client
				SocketWrite= new PrintWriter (SO.getOutputStream());
				if(CO==0)
				{
					send("you are client# " +CO+ " connecting from " +clientaddress);
					log.log("S client# " +CO+ " connected from " +clientaddress);
					while(true)
					{
						String line = SocketRead.readLine();
						
						if (line.equals("quit"))
						{
							send("goodbye");
							SO.close();
							log.log("S client # " +CO+ "disconnected");
							embeddedinterface.shutdownbot();
							sendtoall("Robot Shutdown");
							break;
						}
						else if (line.equals("exit"))
						{
							botdock.terminate();
						}
						else if (line.equals("find"))
						{
							find.find();
						}	
						else 
						{
						sendtoall(line);
						embeddedinterface.move(line);
						find.push(line);
						}
					}
				}				
				
				if(CO>0)
				{
					send("you are client# " +CO+ "connecting from " +clientaddress);
					log.log("S client# " +CO+ " connected from " +clientaddress);
					//these clients should have no robot control
					//server will listen and feedback info about bot
					while(true)
					{
						String line = SocketRead.readLine();
						if (line==null) break;
						if (line.equals("exit"))
						{
							botdock.terminate();
						}
						if (line.equals("quit"))
						{
							send("goodbye");
							SO.close();
							log.log("S client # " +CO+ "disconnected");
							break;
						}
						send(line+ "was received");
					}						
				}
				//if client Number (CO) is negative then send error message and close connection
				else 
				{
					send("-E user limit or battery voltage error try again later, goodbye");
					SO.close();
					log.log("S rejected client from " +clientaddress);
					send("-ERR server capacity has been reached");
				}
				
			}
			catch (Exception e)
			{
				log.log("E with connection because of " +e+ " client# " +CO+ " address " +clientaddress+ "\n");
			}
			log.log("S disconnected " +CO+ " from " +clientaddress);//report to server that client was cutoff
			clientarray[CO]=null;//prepare that client number for next user
		}
		
	//end of ServiceClient Class			
	}