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

import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
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.ProtocolDecoderAdapter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.snmp4j.PDU;
import org.snmp4j.asn1.BER;
import org.snmp4j.asn1.BERInputStream;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OctetString;

import java.io.IOException;

public class SnmpDecoder extends ProtocolDecoderAdapter {
	protected final Logger logger;
    //protected final Logger errLogger;
    
    SocketAdapterContext context;
	ISocketAdapter adapter;
	
	public SnmpDecoder(ISocketAdapter adapter) {
		this.adapter = adapter;
		this.context = adapter.getContext();

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

	public SnmpDecoder() {
	    logger    = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
	    //errLogger = SocketLoggerManager.getInstance().getErrLogger();
	}
	
	public void decode(IoSession session, ByteBuffer buffer, ProtocolDecoderOutput protocolDecoderOutput)
		throws Exception {
		logger.info("SnmpDecoder | " + session + " <RECV>");
		
		java.nio.ByteBuffer pduBuffer = (java.nio.ByteBuffer) buffer.buf();
		
		// decode the bytes using SNMP4J API
		PDU pdu = new PDU();
		try (BERInputStream bis = new BERInputStream(pduBuffer)){
			BER.MutableByte mutableByte = new BER.MutableByte();
//			int length = BER.decodeHeader(bis, mutableByte);
//			int startPos = (int) bis.getPosition();
			
			if (mutableByte.getValue() != BER.SEQUENCE) {
				String txt = "SNMPv2c PDU must start with SEQUENCE";
				throw new IOException(txt);
			}
			
			Integer32 version = new Integer32();
			version.decodeBER(bis);
			
			//decode community string
			OctetString securityName = new OctetString();
			securityName.decodeBER(bis);
			
			// decode the remaining PDU
			pdu.decodeBER(bis);
			logger.info("SnmpDecoder | PDU - " + pdu);
		} catch(Exception e) {
			logger.error("SnmpDecoder | error", e);
		}		
		protocolDecoderOutput.write(pdu);
	}
}
