JSocketMUD/
JSocketMUD/dk/socketmud/
JSocketMUD/dk/socketmud/io/
JSocketMUD/dk/socketmud/object/
JSocketMUD/dk/socketmud/util/
package dk.socketmud.io;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Iterator;

import dk.socketmud.action.CommandSet;
import dk.socketmud.object.Character;
import dk.socketmud.util.Log;

public class SMServer
{
	protected ServerSocket control;
	protected ArrayList<SMClient> clients;

	public SMServer(int port) throws IOException, IllegalArgumentException
	{
		control = new ServerSocket(port);
		clients = new ArrayList<SMClient>();
		control.setSoTimeout(50);

		Log.logString("Accepting connections on port " + port);
	}

	public SMClient acceptNewConnections() throws IOException
	{
		SMClient client;

		try
		{
			Socket s = control.accept();
			client = new SMClient(this, s);
			clients.add(client);
		}
		catch (SocketTimeoutException ex)
		{
			return null;
		}

		return client;
	}

	public void flush()
	{
		Iterator<SMClient> i = clients.iterator();
		while (i.hasNext())
		{
			SMClient client = null;

			try
			{
				client = i.next();
				client.flush();
			}
			catch (IOException ex)
			{
				Log.logString("Failed to flush client. Closing connection");
				i.remove();
				if (client != null)
				{
					try
					{
						client.close();
					}
					catch (IOException e)
					{
						Log.logString("Failed to close connection");
					}
				}

			}
		}
	}
	
	public ArrayList<CommandSet> readCommands()
	{
		ArrayList<CommandSet> cmds = new ArrayList<CommandSet>();
		Iterator<SMClient> i = clients.iterator();

		while (i.hasNext())
		{
			SMClient client = null;

			try
			{
				String command;
				String argument = "";

				client = i.next();
				client.read();

				int index = client.inBuffer.indexOf(' ');
				if (index > -1)
				{
					command = client.inBuffer.substring(0, index);
					argument = client.inBuffer.substring(index + 1);
				}
				else
					command = client.inBuffer;

				if (client.inBuffer != null)
				{
					if (client.state.equals(SMClient.State.Connected))
					{
						if ((command = client.ch.canInterpret(command)) != null)
						{
							CommandSet cmd = new CommandSet(client.ch, argument, command);
							cmds.add(cmd);
						}
						else
							client.ch.writeDuh();
						break;
					}
					else if (client.state.equals(SMClient.State.PromptName))
					{
						client.nameBuffer = command;
						client.write("Are you sure you want to be known as " + client.nameBuffer + " [Y/N]? ");
						client.state = SMClient.State.PromptNameVerify;
					}
					else if (client.state.equals(SMClient.State.PromptNameVerify))
					{
						if (command.equalsIgnoreCase("Y") || command.equalsIgnoreCase("YES"))
						{
							client.ch = new Character(client, client.nameBuffer);
							client.state = SMClient.State.Connected;
							client.write("Welcome to SocketMUD " + client.ch.getName() + "\r\n");
						}
						else if (command.equalsIgnoreCase("N") || command.equalsIgnoreCase("NO"))
						{
							client.write("Then what name do you want? ");
							client.state = SMClient.State.PromptName;
						}
						else
						{
							client.write("What is it, (Y)es or (N)o? ");
						}
					}
					else
					{
						Log.logString("Client in unknown state: " + client.state.toString());
						throw new IOException();
					}
				}
			}
			catch (SocketTimeoutException ex)
			{
				; // not a problem
			}
			catch (IOException ex)
			{
				Log.logString("IOException on client. Closing connection");
				i.remove();
				if (client != null)
				{
					try
					{
						client.close();
					}
					catch (IOException e)
					{
						Log.logString("Failed to close connection");
					}
				}
			}
		}

		return cmds;
	}
}