package com.eactive.eai.adapter.socket2.protocol.law.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.common.util.Logger;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

public class LawRecvEncoder implements ProtocolEncoder {	
	protected final Logger logger;
	protected final Logger errLogger;

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

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

	public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
		ByteMessage m = null;
		if (message == null) {
			throw new Exception("cannot write null message.");
		} else if (message instanceof ByteMessage) {
			m = (ByteMessage) message;
		} else if (message instanceof String) {
			m = new ByteMessage((String) message);
		} else if (message instanceof byte[]) {
			m = new ByteMessage((byte[]) message);
		} else {
			throw new Exception("cannot write unknow format message.");
		}
		
		if(true){
			ByteBuffer lBuffer = ByteBuffer.allocate(m.size() - LawConstants.LL_FIELD_LENGTH);
			lBuffer.put(m.getBytes(0, LawConstants.LL_FIELD_OFFSET_LENGTH));
			lBuffer.put(m.getBytes(LawConstants.LL_FIELD_OFFSET_LENGTH + LawConstants.LL_FIELD_LENGTH));
			lBuffer.flip();
			m.setByteBuffer(lBuffer);		
		}
		
		int length = m.size();
		ByteBuffer buffer = ByteBuffer.allocate( LawConstants.LL_FIELD_LENGTH+length ).limit( LawConstants.LL_FIELD_LENGTH+length  );

		length =length + LawConstants.LL_FIELD_LENGTH;
        /**
         * [1] before-payload
         */
        buffer.put(m.getBytes( 0, LawConstants.LL_FIELD_OFFSET_LENGTH));
		/**
		 * [2] write header
		 */
        String lenStr = CommonLib.getFormatString(length,  LawConstants.LL_FIELD_LENGTH);
        buffer.put(lenStr.getBytes());
        
		
        /**
         * [3] after-payload
         */
        buffer.put(m.getBytes(LawConstants.LL_FIELD_OFFSET_LENGTH, m.getBytes().length - LawConstants.LL_FIELD_OFFSET_LENGTH ));
        
        /**
         * write
         */
        int mark = buffer.position();
        buffer.position(0);
		if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
			logger.debug(context.getAdapterName() + " | LawRecvEncoder | encode : " + CommonLib.hexDump(buffer, context));
			adapter.addRecentSendTrace(session, "LawRecvEncoder | encode : " + CommonLib.hexDump(buffer, context));
		}
        buffer.position(mark);
        buffer.flip();
		out.write(buffer);
		out.flush();
	}

	public void dispose(IoSession session) throws Exception {
		// empty
	}	
}
