package uk.me.graphe.server;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.json.JSONException;
import org.json.JSONObject;

import uk.me.graphe.server.messages.Message;
import uk.me.graphe.server.messages.MessageFactory;

/**
 * reads messages from clients, and validates them. Sends client message pairs
 * to the message processor for transformation
 * 
 * @author Sam Phippen <samphippen@googlemail.com>
 * 
 */
public class ClientMessageHandler extends Thread {

	private ClientManager mClientManager = ClientManager.getInstance();
	private boolean mShutDown = false;
	private MessageProcessor mProcessor;

	private static ClientMessageHandler sInstance = null;

	public ClientMessageHandler() {
	}

	@Override
	public void run() {

		while (!mShutDown) {
			Set<Client> availableClients = mClientManager
					.waitOnReadableClients();
			for (Client c : availableClients) {
				List<String> messages = c.readNextMessages();
				// if this returns null we disconnect the client for sending bad
				// messages
				List<JSONObject> jsos = validateAndParse(messages);
				if (jsos == null)
					mClientManager.disconnect(c);

				List<Message> ops;

				// malformed json == disconect
				try {
					ops = MessageFactory.makeOperationsFromJson(jsos);
					for (Message operation : ops) mProcessor.submit(c, operation);
				} catch (JSONException e) {
					mClientManager.disconnect(c);
				}
				
			}

		}

	}

	private List<JSONObject> validateAndParse(List<String> messages) {
		List<JSONObject> result = new ArrayList<JSONObject>();

		for (String s : messages) {
			try {
				JSONObject o = new JSONObject(s);
				result.add(o);
			} catch (JSONException e) {
				return null;
			}

		}

		return result;

	}

	public static ClientMessageHandler getInstance() {
		if (sInstance == null)
			sInstance = new ClientMessageHandler();
		return sInstance;
	}

}

@@ -153,24 +153,76 @@
 SONObject;%0A%0A
+import uk.me.graphe.graphmanagers.OTGraphManager2d;%0A
 import uk.me
@@ -305,16 +305,70 @@
 Factory;
+%0Aimport uk.me.graphe.server.messages.OpenGraphMessage;
 %0A%0A/**%0A *
@@ -748,16 +748,73 @@
 ocessor;
+%0A%09private HeartbeatManager mHbm = new HeartbeatManager();
 %0A%0A%09priva
@@ -1471,122 +1471,718 @@
 age 
-operation : ops) mProcessor.submit(c, operation);%0A%09%09%09%09%7D catch (JSONException e) %7B%0A%09%09%09%09%09mClientManager.disconnect(c
+message : ops) %7B%0A%09%09%09%09%09    if (message.getMessage().equals(%22heartbeat%22)) %7B%0A%09%09%09%09%09        mHbm.beatWhenPossible(c);%0A%09%09%09%09%09    %7D else if (message.getMessage().equals(%22makegraph%22)) %7B%0A%09%09%09%09%09        int id = DataManager.create();%0A%09%09%09%09%09        c.setCurrentGraphId(id);%0A%09%09%09%09%09        ClientMessageSender.getInstance().sendMessage(c, new OpenGraphMessage(id));%0A%09%09%09%09%09    %7D else if (message.isOperation()) %7B%0A%09%09%09%09%09        mProcessor.submit(c, message);%0A%09%09%09%09%09    %7D else %7B%0A%09%09%09%09%09        throw new Error(%22got unexpected message from client%22);%0A%09%09%09%09%09    %7D%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D catch (JSONException e) %7B%0A%09%09%09%09%09mClientManager.disconnect(c);%0A%09%09%09%09%7D catch (InterruptedException e) %7B%0A%09%09%09%09    mClientManager.disconnect(c);%0A%09%09%09%09    throw new Error(e
 );%0A%09

add some more useful bits to the client message handler