package ch.ethz.globis.disindex.codec;

import ch.ethz.globis.disindex.codec.api.FieldEncoder;
import ch.ethz.globis.disindex.codec.api.ResponseEncoder;
import ch.ethz.globis.distindex.shared.IndexEntry;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;

/**
 * Encodes response messages sent by the server to the client.
 *
 * @param <K>                   The type of the key.
 */
public class ByteResponseEncoder<K> implements ResponseEncoder<K, byte[]>{

    private FieldEncoder<K> keyEncoder;

    public ByteResponseEncoder(FieldEncoder<K> keyEncoder) {
        this.keyEncoder = keyEncoder;
    }

    @Override
    public byte[] encodePut(K key, byte[] value) {
        int valueBytesSize = value.length;
        ByteBuffer buffer = ByteBuffer.allocate(valueBytesSize);
        buffer.put(value);

        return buffer.array();
    }

    @Override
    public byte[] encodeGet(byte[] value) {
        if (value == null) {
            return new byte[] { -1 };
        }
        int valueBytesSize = value.length;
        ByteBuffer buffer = ByteBuffer.allocate(valueBytesSize);
        buffer.put(value);

        return buffer.array();
    }

    @Override
    public byte[] encodeGetRange(List<byte[]> values) {
        throw new UnsupportedOperationException("Operation is not yet implemented!");
    }

    @Override
    public byte[] encodeGetKNN(List<byte[]> values) {
        throw new UnsupportedOperationException("Operation is not yet implemented!");
    }

    @Override
    public byte[] encoderCreate() {
        byte[] response = new byte[] { OpCode.CREATE_INDEX};
        return response;
    }

    public ByteBuffer encode(byte opcode, List<IndexEntry<K, byte[]>> entries) {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        buffer.write(opcode);
        buffer.write(OpStatus.SUCCESS);
        for (IndexEntry<K, byte[]> entry : entries) {
            write(keyEncoder.encode(entry.getKey()), buffer);
            write(entry.getValue(), buffer);
        }
        return ByteBuffer.wrap(buffer.toByteArray());
    }

    public ByteBuffer encodeFailure(byte opcode) {
        int outputBufferSize = 2;
        ByteBuffer buffer = ByteBuffer.allocate(outputBufferSize);
        buffer.put(opcode);
        buffer.put(OpStatus.FAILURE);
        return buffer;
    }

    private void write(byte[] source, ByteArrayOutputStream dest) {
        for (byte b : source) {
            dest.write(b);
        }
    }

}
@@ -138,32 +138,78 @@
 esponseEncoder;%0A
+import ch.ethz.globis.distindex.shared.Index;%0A
 import ch.ethz.g
@@ -334,24 +334,52 @@
 ByteBuffer;%0A
+import java.util.ArrayList;%0A
 import java.
@@ -1791,17 +1791,17 @@
 (byte op
-c
+C
 ode, Lis
@@ -1927,17 +1927,17 @@
 write(op
-c
+C
 ode);%0A  
@@ -2127,32 +2127,32 @@
 lue(), buffer);%0A
-
         %7D%0A      
@@ -2198,32 +2198,403 @@
 rray());%0A    %7D%0A%0A
+    public ByteBuffer encode(byte opCode, IndexEntry%3CK, byte%5B%5D%3E entry) %7B%0A        ByteArrayOutputStream buffer = new ByteArrayOutputStream();%0A        buffer.write(opCode);%0A        buffer.write(OpStatus.SUCCESS);%0A        write(keyEncoder.encode(entry.getKey()), buffer);%0A        write(entry.getValue(), buffer);%0A        return ByteBuffer.wrap(buffer.toByteArray());%0A    %7D%0A%0A
     public ByteB

Index distribution Added method for encoding a single index entry into the response.