package com.eactive.eai.adapter.socket2.protocol.xecure3.envelope;

import com.eactive.eai.adapter.socket2.common.SMSLogger;
import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
import com.eactive.eai.adapter.socket2.protocol.xecure.XecureErrorMessage;
import com.eactive.eai.adapter.socket2.protocol.xecure3.Xecure3Constants;
import com.sf.xc3.XCException;
import com.sf.xc3.XC_v3;
import org.apache.mina.common.IoFilterChain;
import org.apache.mina.common.IoSession;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Xecure3EnvelopeServerFilter extends Xecure3EnvelopeFilter {
	protected byte[] cert;
	protected byte[] key;
	
	public Xecure3EnvelopeServerFilter(ISocketAdapter adapter) {
		super(adapter);
	}	
	
	@Override
	public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {

		cert = readFile(context.getXecure3ServerCert().toString());
		key  = readFile(context.getXecure3CertKey().toString());
		
		IoSession session = parent.getSession();
		
		/**
		 * xc -init
		 */
//		XC_v3 xc = new XC_v3(cert, key , context.getXecure3CertPassword().toString());
		XC_v3 xc = null;//TODO kb version => ¿ìÃ¼±¹ version

		/**
		 * put xc into session
		 */
		session.setAttribute(Xecure3Constants.XECURE3, xc);
			
		/**
		 * change state
		 */
		FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
		if (filterState == null) {
			filterState = new FilterState();
			session.setAttribute(FILTER_STATE_KEY, filterState);
		}
	}
	
	
	@Override
	public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
		ByteMessage m = (ByteMessage) message;
		XC_v3 xc = null;
		FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);

		if("START KB ENVELOPE HANDSHAKE".equals(new String(m.getBytes()))) {
			filterState.state = State.STATE_HANDSHAKE;
			session.setAttribute(SESSION_STATE, filterState.state.toString());
		}
		
		try {

			xc = (XC_v3) session.getAttribute(Xecure3Constants.XECURE3);
	
			switch (filterState.state) {
			case STATE_HANDSHAKE:
				if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
					logger.debug(context.getAdapterName() + " | Xecure3EnvelopeServerFilter | <STATE_HANDSHAKE> ");
				}
				
//				session.write(XCPem.encodePemFile(context.getXecure3ServerCert(), "certificate"));
				
				filterState.state = State.STATE_FINAL;
				setSessionState(session, filterState.state.toString());	
				
			break;

			case STATE_FINAL:
				
//				XCPem.decodePemFile(context.getXecure3ClientCert(), m.getString());
				if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
					logger.debug(context.getAdapterName() + " | Xecure3EnvelopeServerFilter | <STATE_FINAL> ");
				}
				
//				try {
//					logger.debug(context.getAdapterName() + " | Xecure3EnvelopeServerFilter | <messageReceived> Before getChainCertInfo | ");
//					logger.debug(context.getAdapterName() + context.getXecure3ClientCert() + context.getXecure3CertStore());
//					
//					XCNpki.getChainCertInfo(context.getXecure3ClientCert(),context.getXecure3CertStore());
//					
//					if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
//						logger.debug(context.getAdapterName() + " | Xecure3EnvelopeServerFilter | <getChainCertInfo> ");
//					}
//					
//					String KeyFinal_Message = "ENVELOPE FINAL HANDSHAKE";	
//					session.write(KeyFinal_Message);
//					
//					filterState.state = State.STATE_MESSAGE;
//					setSessionState(session, filterState.state.toString());	
//					
//				} catch (XCException e) {
//					adapter.addRecentError(context.getAdapterName() + " | xecure error - ", e);
//					logger.error(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | ", e);
//					errLogger.error(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | ", e);
//					SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
//					
//					nextFilter.filterClose(session);
//					if (xc != null) {
//						xc.close();
//					}
//					adapter.getSessionPool().remove(session);
//					session.close();
//					
//					throw new XCException(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | ");
//				}
						
				nextFilter.sessionCreated(session);
				nextFilter.sessionOpened(session);
				
			break;
				
			case STATE_MESSAGE:
				if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
					logger.debug(context.getAdapterName() + " | Xecure3EnvelopeServerFilter | <STATE_MESSAGE> ");
				}
				
				m = new ByteMessage(xc.envdec(m.getBytes(), readFile(context.getXecure3ServerCert()),readFile(context.getXecure3CertKey()),context.getXecure3CertPassword()));


				nextFilter.messageReceived(session, m);
				
			break;
		
			default:
				throw new Exception("<RECV> invalid message during handshake .. : " + m);
			}
		} catch(XCException e) {
			String xcMessage = "";
			Matcher matcher = Pattern.compile("(\\-[0-9]+)").matcher(e.getMessage());
			
			if (matcher.find()) {
			    String keyValue = matcher.group(1);
			    xcMessage = XecureErrorMessage.getErrorMessage(keyValue);
			}
			
			adapter.addRecentError(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + xcMessage, e);
			logger.error(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + xcMessage, e);
			errLogger.error(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + xcMessage, e);
			SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");

		//	nextFilter.filterClose(session);
		//	if (xc != null) {
		//		xc.close();
		//	}
		//	adapter.getSessionPool().remove(session);
		//	session.close();

			throw new XCException(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + xcMessage);
		}
	}
	
	
	@Override
    public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
		ByteMessage m = null;
		
		if (writeRequest.getMessage() instanceof byte[]) {
			m = new ByteMessage((byte[]) writeRequest.getMessage());
		} else if (writeRequest.getMessage() instanceof ByteMessage) {
			m = (ByteMessage) writeRequest.getMessage();
		} else if (writeRequest.getMessage() instanceof String) {
			m = new ByteMessage((String) writeRequest.getMessage());
		} else {
			throw new Exception("Unknown data format");
		}  
		
		FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
		XC_v3 xc = (XC_v3) session.getAttribute(Xecure3Constants.XECURE3);
		
		try {

			if(State.STATE_MESSAGE.equals(filterState.state)) {
				
				m = new ByteMessage(xc.envenc(m.getBytes(), readFile(context.getXecure3ClientCert())));
				
			}


		} catch(Exception e) {

			String Message = "";
			Matcher matcher = Pattern.compile("(\\-[0-9]+)").matcher(e.getMessage());
			if (matcher.find()) {
			    String keyValue = matcher.group(1);
			    Message = XecureErrorMessage.getErrorMessage(keyValue);
			}
			adapter.addRecentError(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + Message, e);
			logger.error(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + Message, e);
			errLogger.error(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + Message, e);
			SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
			
			nextFilter.filterClose(session);
			if (xc != null) {
				xc.close();
			}
			adapter.getSessionPool().remove(session);
			session.close();
			
			throw new XCException(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + Message);
		}

		nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
    }
}
