package common.network;

import javax.crypto.Cipher;
import javax.crypto.ShortBufferException;

import common.net.buffer.ByteBuf;
import common.net.channel.ChannelHandlerContext;

public class EncryptionCodec {
	private final Cipher cipher;
	private byte[] receiveBuf = new byte[0];
	private byte[] encodeBuf = new byte[0];

	protected EncryptionCodec(Cipher cipher) {
		this.cipher = cipher;
	}

	private byte[] readBuffer(ByteBuf buf) {
		int size = buf.readableBytes();
		if(this.receiveBuf.length < size)
			this.receiveBuf = new byte[size];
		buf.readBytes((byte[])this.receiveBuf, 0, size);
		return this.receiveBuf;
	}

	protected ByteBuf decipher(ChannelHandlerContext ctx, ByteBuf buffer) throws ShortBufferException {
		int size = buffer.readableBytes();
		byte[] data = this.readBuffer(buffer);
		ByteBuf buf = ctx.alloc().heapBuffer(this.cipher.getOutputSize(size));
		buf.writerIndex(this.cipher.update(data, 0, size, buf.array(), buf.arrayOffset()));
		return buf;
	}

	protected void cipher(ByteBuf in, ByteBuf out) throws ShortBufferException {
		int size = in.readableBytes();
		byte[] data = this.readBuffer(in);
		int csize = this.cipher.getOutputSize(size);
		if(this.encodeBuf.length < csize)
			this.encodeBuf = new byte[csize];
		out.writeBytes((byte[])this.encodeBuf, 0, this.cipher.update(data, 0, size, this.encodeBuf));
	}
}
