import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.*;
import java.io.*;

class Message // this is what is passed to and fro?
{
    private ClientInterface client;
    private String message;
    
    public Message (ClientInterface c, String msg)
    {
	super();
	client = c;
	message=msg;
    }
    public ClientInterface getClient() {return client;}
    public String getMessage() {return message;}
    
}

/*
class Ticker extends Thread
{
    public Ticker()
    {
	run();
    }
    public void run()
    {
	try{sleep(20);} catch(Exception e)
	    {
		e.printStackTrace();
	    }
	//System.out.println("hi!");
	//advanceClient();
    }
}
*/

public class Server extends Thread implements ServerInterface
    // RemoteChatServer is the remote interface
{
    private Vector clients = new Vector(); // list of clients connected   
    private Vector messages = new Vector(); // temporary buffer for messages??
    private Vector existingWords = new Vector();
    //private int totalscore = 0;
    private String[] nameArray = new String[5];
    private int[] scoreArray = new int[5];
    private ClientInterface activeClient;
    private char[][] boardArray={{'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'},
				 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0','0'}};

    //public Ticker t=new Ticker();
    private String[] words = new String[45402];
    
    public Server() throws RemoteException
    {
	super(); // what does this do?
	UnicastRemoteObject.exportObject(this);
    }

    public void connect (ClientInterface client) 
    
    {
	try
	    {
		System.out.println("client: "+client.getClientName()+" tried to connect");
		synchronized (clients)
		    {
			if (clients.contains(client)) {return;}
			clients.addElement(client);
			System.out.print(" added ");
		    }
		
		if (clients.size()==1)
		    {
			System.out.println("first client");
			activeClient=client;
			activeClient.activate();
			sendMessage(activeClient, " to play");
			client.setFirstTime(true);
		    }
		else
		    {
			System.out.println("not first client");
			client.setFirstTime(false);
			client.deactivate();
		    }
	

		sendMessage(client, "connected as Client["+(clients.size()-1)+"]");
		// advanceClient();
		client.receiveData(boardArray,existingWords,nameArray,scoreArray);
		
	    }
	catch (Exception e)
	    {
		clients.removeElement(client);
	    }
    }

    public boolean validString(String s)
    {
	//if (clients.size()>1)
	    {
		System.out.print(s + "received at server ");
		
		for(int i=0;i<words.length;i++)
		    {
			if(words[i].compareToIgnoreCase(s)==0)
			    {
				System.out.println(" found ");
				return true;
			    }
		    }
		System.out.println(" not found ");
	    }
	    //else System.out.println(" sorry! min 2 players");
	return false;
    }
    
    public void sendMessage (ClientInterface client, String msg) //adds message to buffer, which is emptied??
    {
	synchronized (messages)
	    {
		messages.addElement(new Message(client, msg));
	    }
    }


    public void receiveData(ClientInterface client, char[][] bA, NewVector words) 
    {
	System.out.println("receiving data in server from client "+clients.indexOf(client));
	System.out.println("active client now client["+clients.indexOf(activeClient)+"]");;
	int i;

	existingWords.addAll(words);
	
	System.out.print("received data at server - existing words are ");
	for (i=0;i<existingWords.size();i++)
	    System.out.print((String)existingWords.elementAt(i)+" ");
	System.out.println();
	
	boardArray=bA;
	try
	    {
		for (i=0; i<clients.size();i++)
		    {
			nameArray[i] =((ClientInterface)( clients.elementAt(i))).getClientName();
			scoreArray[i]=((ClientInterface)( clients.elementAt(i))).getClientScore();
		    }
	    }
	catch (Exception e)
	    {
		e.printStackTrace();
	    }
	
	
	for (i=0; i<clients.size();i++)
	    {
		ClientInterface tempClient= (ClientInterface)clients.elementAt(i);
		try{tempClient.receiveData(boardArray, existingWords, nameArray, scoreArray);}
		catch(Exception e)
		    {
			e.printStackTrace();
			try{advanceClient();} catch (Exception e1){}
			clients.removeElement(tempClient);
		    }
		
	    }
	advanceClient();
    }
	
    
    public void advanceClient() 
    {
	if (activeClient.equals(clients.lastElement()))
	    activeClient=(ClientInterface)clients.elementAt(0);
	else activeClient=(ClientInterface)clients.elementAt(clients.indexOf(activeClient)+1);
	//System.out.println("active client now client["+clients.indexOf(activeClient)+"]");;
	sendMessage(activeClient, " to play");
	try
	    {
		activeClient.activate();
		for(int i=0; i<clients.size();i++)
		    if(!(activeClient.equals((ClientInterface)clients.elementAt(i))))
			((ClientInterface)clients.elementAt(i)).deactivate();

		if (existingWords.size()==0) activeClient.setFirstTime(true);
	    }
	catch (Exception e) {e.printStackTrace();}
    }
    
    public void run()
    {
	
	while (true)
	    {
		Message[] msgs;
		try {Thread.sleep(500);}
		catch (InterruptedException e) {}
		synchronized (messages)
		    {
			if (messages.size()>0)
			    {
				msgs = new Message[messages.size()];
				messages.copyInto(msgs);
				messages.removeAllElements();
			    }
			else {continue;}
		    }

		for(int i=0; i<msgs.length; i++)
		    {
			ClientInterface c = msgs[i].getClient();
			String msg = msgs[i].getMessage();
			Enumeration targs;
			String nom;
			try {nom = c.getClientName();}
			catch (Exception e)
			    {
				//e.printStackTrace;
				continue;
			    }
			targs=clients.elements();
			while (targs.hasMoreElements())
			    {
				ClientInterface target=(ClientInterface) targs.nextElement();
				try {target.receiveMessage(nom+": "+msg);}
				catch (Exception e)
				    {
					synchronized (clients)
					    {
						clients.removeElement(target);
					    }
				    }
			    }
		    }
	    }
    }
   public static void main(String[] args)
    {
	System.out.println("starting main");
	// load words into array of strings
	try
	    {
		Server server = new Server();
		try
		    {
			String word = new String();
			int wordcount=0;
			
			FileReader fr = new FileReader("words");
			BufferedReader br = new BufferedReader(fr);
			
			while((word = br.readLine())!=null)
			    {
				server.words[wordcount]=word;
				wordcount++;
			    }
		    }
		catch (IOException e)
		    {
			System.out.println("oh! got an error");
			e.printStackTrace();
		    }
		
		
		Naming.rebind("Server", server);
		server.start();
	    }
	catch (Exception e)
	    {
		System.out.println("oh god!");
		e.printStackTrace();
	    }
    }
}






