
package forager.server;

import java.io.ByteArrayInputStream;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import forager.events.ForagerEventType;

import galileo.event.Event;
import galileo.event.EventHandler;
import galileo.event.EventTypeMap;
import galileo.net.GalileoMessage;
import galileo.net.MessageListener;
import galileo.net.NetworkDestination;
import galileo.serialization.SerializationInputStream;

public class EventMapper implements MessageListener {

    private static final Logger logger = Logger.getLogger("galileo");

    private Class<?> handlerClass;
    private Object handlerObject;

    private EventMap eventMap;

    private Map<Class<?>, Method> classToMethod = new HashMap<>();

    public EventMapper(Object handlerObject, EventMap eventMap) {
        this.handlerClass = handlerObject.getClass();
        this.handlerObject = handlerObject;
        this.eventMap = eventMap;
        System.out.println(EventMap.getClass(1));
    }

    public <T extends Event> void map(EventTypeMap typeMap, Class<T> type) {

    }

    public void linkEventHandlers() {
        for (Method m : handlerClass.getMethods()) {
            for (Annotation a : m.getAnnotations()) {
                if (a.annotationType().equals(EventHandler.class)) {
                    /* This method is an event handler */
                    Class<?>[] params = m.getParameterTypes();
                    Class<?> eventClass = extractEventClass(params);
                    logger.log(Level.INFO,
                            "Linking handler method [{0}] to class [{1}]",
                            new Object[] { m.getName(), eventClass.getName() });
                    classToMethod.put(eventClass, m);
                    break;
                }
            }
        }
    }

    private Class<?> extractEventClass(Class<?>[] parameters) {
        if (parameters.length <= 0) {
            //TODO throw new exception
        }

        List<Class<?>> interfaces
            = Arrays.asList(parameters[0].getInterfaces());
        if (interfaces.contains(Event.class) == false) {
            //TODO throw error
        }

        return parameters[0];
        //classToMethod.put(parameters[0], m);
    }


    @Override
    public void onConnect(NetworkDestination endpoint) {

    }

    @Override
    public void onDisconnect(NetworkDestination endpoint) {

    }

    @Override
    public void onMessage(GalileoMessage message) {
        SerializationInputStream in = new SerializationInputStream(
                new ByteArrayInputStream(message.getPayload()));
        int type = 0;
        try {
        type = in.readInt();
        } catch (IOException e) { }
        System.out.println(ForagerEventType.fromInt(type));
        System.out.println(
                ((SocketChannel) message.getSelectionKey().channel()).socket().getInetAddress().getHostName());
    }

}

@@ -364,49 +364,8 @@
 r;%0A%0A
-import forager.events.ForagerEventType;%0A%0A
 impo
@@ -622,16 +622,57 @@
 tStream;
+%0Aimport galileo.serialization.Serializer;
 %0A%0Apublic
@@ -1186,17 +1186,17 @@
 println(
-E
+e
 ventMap.
@@ -1220,93 +1220,8 @@
  %7D%0A%0A
-    public %3CT extends Event%3E void map(EventTypeMap typeMap, Class%3CT%3E type) %7B%0A%0A    %7D%0A%0A
     
@@ -2816,95 +2816,191 @@
     
-%7D catch (IOException e) %7B %7D%0A        System.out.println(ForagerEventType.fromInt(type));
+Event e = Serializer.deserializeFromStream(eventMap.getClass(type), in);%0A        classToMethod.get(eventMap.getClass(type)).invoke(handlerObject, e);%0A        %7D catch (Exception e) %7B %7D
 %0A   

Add deserialization