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.IoSession;

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

public class Xecure3EnvelopeClientFilter extends Xecure3EnvelopeFilter {
	public Xecure3EnvelopeClientFilter(ISocketAdapter adapter) {
		super(adapter);
	}	
	
	@Override
    public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
		/**
		 * xc - init
		 */
		XC_v3 xc = new XC_v3();
		
		/**
		 * 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);
		}
		filterState.state = State.STATE_HANDSHAKE;
		session.setAttribute(SESSION_STATE, filterState.state.toString());

		String KeyInitMessage = "START KB ENVELOPE HANDSHAKE";	
		session.write(KeyInitMessage);

	}
	
	@Override
	public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
		ByteMessage m = (ByteMessage) message;
		
		FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
		XC_v3 xc = (XC_v3) session.getAttribute(Xecure3Constants.XECURE3);

		try {
			
			switch (filterState.state) {			
			case STATE_HANDSHAKE:

//				String sessionState = (String) session.getAttribute(ProtocolHandler.SESSION_STATE);

//				XCPem.decodePemFile(context.getXecure3ServerCert(), m.getString());
				
//				try {

//					XCNpki.getChainCertInfo(context.getXecure3ServerCert(),context.getXecure3CertStore());
					
//				} 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() + " | ");
//				}
				
//				session.write(XCPem.encodePemFile(context.getXecure3ClientCert(), "certificate"));
				
				filterState.state = State.STATE_FINAL;
				setSessionState(session, filterState.state.toString());	

				break;
				
			case STATE_FINAL:
				
				if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
					logger.debug(context.getAdapterName() + " | Xecure3EnvelopeClientFilter | <messageReceived STATE_FINAL> ");					
				}
				
				filterState.state = State.STATE_MESSAGE;
				setSessionState(session, filterState.state.toString());	
				
				nextFilter.sessionCreated(session);
				nextFilter.sessionOpened(session);

				break;
				
			case STATE_MESSAGE:			
				if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
					logger.debug(context.getAdapterName() + " | Xecure3EnvelopeClientFilter | <messageReceived STATE_MESSAGE> ");					
				}

				m = new ByteMessage(xc.envdec(m.getBytes(), readFile(context.getXecure3ClientCert()),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 key = matcher.group(1);
			    xcMessage = XecureErrorMessage.getErrorMessage(key);
			}
			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.getXecure3ServerCert())));

			}
							
		} catch(XCException e) {
			String xcMessage = "";
			Matcher matcher = Pattern.compile("(\\-[0-9]+)").matcher(e.getMessage());
			if (matcher.find()) {
			    String key = matcher.group(1);
			    xcMessage = XecureErrorMessage.getErrorMessage(key);
			}
			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);
		}

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