package com.eactive.eai.adapter.socket2.protocol.fixedheader.codec;

import com.eactive.eai.adapter.socket2.common.CommonLib;
import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
import com.eactive.eai.common.util.Logger;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

public class ChunkDecoder extends ProtocolDecoderAdapter  {
	final protected Logger logger;
    final protected Logger errLogger;
	
	public static final int MAX_PAYLOAD_SIZE = 25 * 1024 * 1024;   // 25MB

	private static final String DECODER_STATE_KEY = ChunkDecoder.class.getName() + ".STATE";

	private static class CodecState {
		ByteBuffer 	buffer = ByteBuffer.allocate(0).setAutoExpand(true);
		//int      	payloadSize;
	}
	
	SocketAdapterContext context;
	ISocketAdapter adapter;

	public ChunkDecoder(ISocketAdapter adapter) {
		this.adapter = adapter;
		this.context = adapter.getContext();

	    logger    = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
	    errLogger = SocketLoggerManager.getInstance().getErrLogger();
	}

	public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
		if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
			logger.debug(context.getAdapterName() + " | ChunkDecoder | decode : " + CommonLib.hexDump(in, context));
			adapter.addRecentRecvTrace(session, "ChunkDecoder | decode : " + CommonLib.hexDump(in, context));
		}
		
		CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);

		if (codecState == null) {
			codecState = new CodecState();
			codecState.buffer.limit(context.getRecvPayloadLength());
			//codecState.payloadSize = context.getPayloadLength();
			session.setAttribute(DECODER_STATE_KEY, codecState);
		}


		session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
		
		codecState.buffer.limit(in.position());
		codecState.buffer.put(in);
		
		byte[] bytes = new byte[codecState.buffer.limit()];
		codecState.buffer.position(0);
		codecState.buffer.get(bytes);
		ByteMessage message = new ByteMessage(bytes);
		out.write(message);
		
		codecState.buffer.position(0);
		if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
			session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
		} else {
			session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
		}

		session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
	}
}
