package no.found.elasticsearch.transport.netty;

import org.elasticsearch.Version;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.common.netty.buffer.ChannelBuffer;
import org.elasticsearch.common.netty.buffer.ChannelBuffers;
import org.elasticsearch.common.netty.channel.*;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;

public class FoundPrefixer extends SimpleChannelHandler {
    private final String clusterName;
    private final String apiKey;

    public FoundPrefixer(String clusterName, String apiKey) {
        this.clusterName = clusterName;
        this.apiKey = apiKey;
    }

    private boolean prefixed = false;

    @Override
    public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        super.connectRequested(ctx, e);
    }

    @Override
    public void channelBound(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        super.channelBound(ctx, e);

        prefixed = false;
    }

    @Override
    public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        if(!prefixed) {
            prefixed = true;

            SocketAddress remoteAddress = ctx.getChannel().getRemoteAddress();

            if(remoteAddress instanceof InetSocketAddress) {
                String remoteName = ((InetSocketAddress)remoteAddress).getHostString();
                if(remoteName.contains(".foundcluster.com") || remoteName.contains(".localhacks.com")) {
                    sendPrefix(ctx);
                }
            }
        }
        ctx.sendDownstream(e);
    }

    protected ChannelFuture sendPrefix(ChannelHandlerContext ctx) throws IOException {
        return ctx.getChannel().write(getPrefixBuffer());
    }

    public ChannelBuffer getPrefixBuffer() throws IOException {
        int versionLength = 4;
        byte[] clusterNameBytes = clusterName.getBytes(StandardCharsets.UTF_8);
        int clusterNameLength = clusterNameBytes.length;

        byte[] apiKeyBytes = apiKey.getBytes(StandardCharsets.UTF_8);
        int apiKeyLength = apiKeyBytes.length;

        return ChannelBuffers.wrappedBuffer(
            concat(getIntBytes(versionLength + 4 + clusterNameLength + 4 + apiKeyLength),

                    getIntBytes(Version.CURRENT.id),

                    getIntBytes(clusterNameLength),
                    clusterNameBytes,

                    getIntBytes(apiKeyLength),
                    apiKeyBytes
            )
        );
    }

    protected byte[] getIntBytes(int i) throws IOException {
        byte[] bytes = new byte[4];

        bytes[0] = ((byte) (i >> 24));
        bytes[1] = ((byte) (i >> 16));
        bytes[2] = ((byte) (i >> 8));
        bytes[3] = ((byte) i);

        return bytes;
    }

    protected byte[] concat(byte[]... allBytes) {
        int size = 0;
        for (byte[] allByte1 : allBytes) {
            size += allByte1.length;
        }

        byte[] result = new byte[size];
        int current = 0;

        for (byte[] allByte : allBytes) {
            for (byte anAllByte : allByte) {
                result[current++] = anAllByte;
            }
        }
        return result;
    }
}

@@ -461,37 +461,8 @@
 xer 
-extends SimpleChannelHandler 
 %7B%0A  
@@ -540,1277 +540,275 @@
    p
-ublic FoundPrefixer(String clusterName, String apiKey) %7B%0A        this.clusterName = clusterName;%0A        this.apiKey = apiKey;%0A    %7D%0A%0A    private boolean prefixed = false;%0A%0A    @Override%0A    public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception %7B%0A        super.connectRequested(ctx, e);%0A    %7D%0A%0A    @Override%0A    public void channelBound(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception %7B%0A        super.channelBound(ctx, e);%0A%0A        prefixed = false;%0A    %7D%0A%0A    @Override%0A    public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception %7B%0A        if(!prefixed) %7B%0A            prefixed = true;%0A%0A            SocketAddress remoteAddress = ctx.getChannel().getRemoteAddress();%0A%0A            if(remoteAddress instanceof InetSocketAddress) %7B%0A                String remoteName = ((InetSocketAddress)remoteAddress).getHostString();%0A                if(remoteName.contains(%22.foundcluster.com%22) %7C%7C remoteName.contains(%22.localhacks.com%22)) %7B%0A                    sendPrefix(ctx);%0A                %7D%0A            %7D%0A        %7D%0A        ctx.sendDownstream(e)
+rivate static final int revisionLength = 4;%0A    private static final int revision = 1;%0A%0A    private static final int versionLength = 4;%0A%0A    public FoundPrefixer(String clusterName, String apiKey) %7B%0A        this.clusterName = clusterName
 ;%0A    
-%7D%0A%0A
     
-protected ChannelFuture sendPrefix(ChannelHandlerContext ctx) throws IOException %7B%0A        return ctx.getChannel().write(getPrefixBuffer())
+this.apiKey = apiKey
 ;%0A  
@@ -880,39 +880,8 @@
 n %7B%0A
-        int versionLength = 4;%0A
     
@@ -1208,16 +1208,41 @@
 ntBytes(
+4 + revisionLength + 4 + 
 versionL
@@ -1289,24 +1289,165 @@
 eyLength),%0A%0A
+                    getIntBytes(revisionLength),%0A                    getIntBytes(revision),%0A%0A                    getIntBytes(versionLength),%0A
             

send header revision id