package ecse414.fall2015.group21.game.shared.data;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import io.netty.buffer.ByteBuf;

/**
 *
 */
public interface Packet {
    Type getType();

    ByteBuf asRaw();

    interface UDP extends Packet {
        Factory<Packet.UDP> FACTORY = new Factory<>();
    }

    interface TCP extends Packet {
        Factory<Packet.TCP> FACTORY = new Factory<>();
    }

    enum Type {
        CONNECT_REQUEST(0),
        CONNECT_FULFILL(1),
        TIME_SYNC_REQUEST(2),
        TIME_SYNC_FULFILL(3),
        PLAYER_STATE(4),
        PLAYER_SHOOT(5),
        PLAYER_HEALTH(6);
        public static final Type[] BY_ID = values();
        public final byte id;

        Type(int id) {
            this.id = (byte) id;
        }
    }

    class Factory<T extends Packet> {
        private final Map<Byte, Constructor<? extends T>> constructors = new HashMap<>();

        public void register(Class<? extends T> packet, Packet.Type... types) {
            try {
                final Constructor<? extends T> constructor = packet.getDeclaredConstructor(ByteBuf.class);
                constructor.setAccessible(true);
                for (Type type : types) {
                    constructors.put(type.id, constructor);
                }
            } catch (NoSuchMethodException exception) {
                throw new RuntimeException(exception);
            }
        }

        @SuppressWarnings("unchecked")
        public <I extends T> I newInstance(ByteBuf buf) {
            try {
                return (I) constructors.get(buf.getByte(0)).newInstance(buf);
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException exception) {
                throw new RuntimeException(exception);
            }
        }
    }
}

@@ -227,213 +227,819 @@
 *%0A *
-%0A */%0Apublic interface Packet %7B%0A    Type getType();%0A%0A    ByteBuf asRaw();%0A%0A    interface UDP extends Packet %7B%0A        Factory%3CPacket.UDP%3E FACTORY = new Factory%3C%3E();%0A    %7D%0A%0A    interface TCP extends Packet %7B
+ Represents a packet to be converted to a byte buffer and sent over the network. Exists in two flavours: UDP and TCP%0A */%0Apublic interface Packet %7B%0A    /**%0A     * Returns the packet type.%0A     *%0A     * @return The type%0A     */%0A    Type getType();%0A%0A    /**%0A     * Stores the packet information in a new byte buffer for sending over the network.%0A     *%0A     * @return The packet as a buffer%0A     */%0A    ByteBuf asRaw();%0A%0A    /**%0A     * A UDP packet.%0A     */%0A    interface UDP extends Packet %7B%0A        /**%0A         * A factory for converting from byte buffers to UDP packets.%0A         */%0A        Factory%3CPacket.UDP%3E FACTORY = new Factory%3C%3E();%0A    %7D%0A%0A    /**%0A     * A TCP packet.%0A     */%0A    interface TCP extends Packet %7B%0A        /**%0A         * A factory for converting from byte buffers to TCP packets.%0A         */
 %0A   
@@ -1093,24 +1093,69 @@
 %3E();%0A    %7D%0A%0A
+    /**%0A     * All the packet types.%0A     */%0A
     enum Typ
@@ -1362,285 +1362,890 @@
     
-public static final Type%5B%5D BY_ID = values();%0A        public final byte id;%0A%0A        Type(int id) %7B%0A            this.id = (byte) id;%0A        %7D%0A    %7D%0A%0A    class Factory%3CT extends Packet%3E %7B%0A        private final Map%3CByte, Constructor%3C? extends T%3E%3E constructors = new HashMap%3C%3E();%0A
+/**%0A         * Converts from an ID to a packet type.%0A         */%0A        public static final Type%5B%5D BY_ID = values();%0A        /**%0A         * Gets the packet type ID.%0A         */%0A        public final byte id;%0A%0A        Type(int id) %7B%0A            this.id = (byte) id;%0A        %7D%0A    %7D%0A%0A    /**%0A     * A factory that uses reflection to call the proper packet constructor for the given byte buffer. The first byte of the packet is used as the ID of the type. Packets are registered by type.%0A     *%0A     * @param %3CT%3E The type of packet%0A     */%0A    class Factory%3CT extends Packet%3E %7B%0A        private final Map%3CByte, Constructor%3C? extends T%3E%3E constructors = new HashMap%3C%3E();%0A%0A        /**%0A         * Registers a packet class for the given types.%0A         *%0A         * @param packet The packet class to use for the types%0A         * @param types The types the packet class represents%0A         */
 %0A   
@@ -2747,24 +2747,407 @@
 %0A        %7D%0A%0A
+        /**%0A         * Gets the first byte of the buffer, converts it to a packet type and looks for a constructor for that type. On success, constructs a new packet from the buffer.%0A         *%0A         * @param buf The buffer to construct the packet from%0A         * @param %3CI%3E The expected type of packet that will be constructed%0A         * @return The resulting packet%0A         */%0A
         @Sup

Add some javadocs in the Packet class