package org.skife.memcake;

import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler;

public class Response {
    private final Connection conn;
    private final ByteBuffer headerBuffer;

    private final byte magic;
    private final byte opcode;
    private final char keyLength;
    private final byte extrasLength;
    private final byte dataType;
    private final int totalBodyLength;
    private final int opaque;
    private final long cas;
    private final ByteBuffer bodyBuffer;
    private final char status;
    private Integer flags;
    private byte[] value;
    private byte[] key;

    public Response(Connection conn, ByteBuffer buf) {
        this.conn = conn;
        headerBuffer = buf;
        magic = buf.get();
        opcode = buf.get();
        keyLength = buf.getChar();
        extrasLength = buf.get();
        dataType = buf.get();
        status = buf.getChar();
        totalBodyLength = buf.getInt();
        opaque = buf.getInt();
        cas = buf.getLong();
        bodyBuffer = ByteBuffer.allocate(totalBodyLength);
        headerBuffer.clear();
    }

    public void readBody() {
        conn.getChannel().read(bodyBuffer, bodyBuffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer bytesRead, ByteBuffer bodyBuffer) {
                if (bodyBuffer.remaining() != 0) {
                    readBody();
                    return;
                }

                bodyBuffer.flip();
                switch (opcode) {
                    case Opcodes.set:
                        readSetBody(bodyBuffer);
                        break;
                    case Opcodes.get:
                        readGetBody(bodyBuffer);
                        break;
                    default:
                        System.err.printf("unhandled opcode: %d\n", opcode);

                }
                finished();
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                conn.networkFailure(exc);
            }
        });
    }

    private void finished() {
        conn.nextResponse(headerBuffer);
    }

    private void readSetBody(ByteBuffer bodyBuffer) {
        conn.receive(this);
    }

    private void readGetBody(ByteBuffer bodyBuffer) {
        this.flags = bodyBuffer.getInt();
        if (this.keyLength != 0) {
            this.key = new byte[keyLength];
            bodyBuffer.get(key);
        }
        this.value = new byte[this.totalBodyLength - this.keyLength - this.extrasLength];
        bodyBuffer.get(this.value);
        conn.receive(this);
    }

    public int getOpaque() {
        return opaque;
    }

    public long getVersion() {
        return cas;
    }

    public Integer getFlags() {
        return flags;
    }

    public byte[] getValue() {
        return value;
    }
}

@@ -94,23 +94,16 @@
 ndler;%0A%0A
-public 
 class Re
@@ -606,23 +606,16 @@
 y;%0A%0A    
-public 
 Response
@@ -1086,31 +1086,24 @@
 %0A    %7D%0A%0A    
-public 
 void readBod
@@ -2631,23 +2631,16 @@
  %7D%0A%0A    
-public 
 int getO
@@ -2683,23 +2683,16 @@
  %7D%0A%0A    
-public 
 long get
@@ -2734,23 +2734,16 @@
  %7D%0A%0A    
-public 
 Integer 
@@ -2788,23 +2788,16 @@
  %7D%0A%0A    
-public 
 byte%5B%5D g

clean up Response visibility