package com.eactive.eai.adapter.socket2.protocol.xecure.fixedheader.handshake;

import com.eactive.eai.adapter.socket2.common.SMSLogger;
import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
import com.eactive.eai.adapter.socket2.protocol.xecure.XecureConstants;
import com.eactive.eai.adapter.socket2.protocol.xecure.XecureErrorMessage;
import com.sf.xc3.Base64;
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 XecureFixedHeaderClientFilter extends XecureFixedHeaderFilter {
	public XecureFixedHeaderClientFilter(ISocketAdapter adapter) {
		super(adapter);
	}	
	
	
	@Override
    public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
		try {
			/**
			 * xc - init
			 */
			XC_v3 xc = new XC_v3();
			int ret = xc.init(password, context.getXecureConfigPath(), 1);
			if (ret < 0) {
				throw new Exception("cannot init xecure connector. ret=" + ret + " : " + XecureErrorMessage.getErrorMessage(ret));
			}
			
			//set default : msgShort
			//xc.msgLong();

			/**
			 * put xc into session
			 */
			session.setAttribute(XecureConstants.XECURE, 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_KEY_INIT;
			session.setAttribute(SESSION_STATE, filterState.state.toString());

//			String base64 = xc.keyInit(remoteCert);
			String base64 = "";//TODO kb version => ¿ìÃ¼±¹ version
			//byte[] token = Base64.decode(base64);
			if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
				logger.debug(context.getAdapterName() + " | XecureFixedHeaderClientFilter | <SEND> KEY_INIT | " + base64.substring(0, 40) + "...");
			}	
			
//			WriteFuture future = session.write(format(base64.getBytes(), XecureConstants.FIXED_HEADER_HANDSHAKE.getBytes(), session));
			session.write(format(base64.getBytes(), XecureConstants.FIXED_HEADER_HANDSHAKE.getBytes(), session));
			//future.join(context.getTimeout() * 1000L);
			//internalSendMessage(session, new ByteMessage(Constants.KEY_INIT_MESSAGE));
			
			filterState.state = State.STATE_KEY_FINAL;
			setSessionState(session, filterState.state.toString());
		} 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.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
			SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
			throw new XCException(context.getAdapterName() + " | " + e.getMessage() + " | " + xcMessage);
		}
	}
	
	
	@Override
	public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
		ByteMessage m = (ByteMessage) message;

		try {
			FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
			XC_v3 xc = (XC_v3) session.getAttribute(XecureConstants.XECURE);
	
			switch (filterState.state) {			
			case STATE_KEY_FINAL:
				if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
					logger.debug(context.getAdapterName() + " | XecureFixedHeaderClientFilter | <RECV> KEY_FINAL | " + m);
				}
	
				filterState.state = State.STATE_MESSAGE;
				setSessionState(session, filterState.state.toString());	

//				String sessionState = (String) session.getAttribute(ProtocolHandler.SESSION_STATE);
				
				ByteMessage bm = new ByteMessage(m.getBytes(context.getLlFieldLength() + XecureConstants.FIXED_HEADER_PART_LEHGTH));
				m = bm;

				byte[] bytes = Base64.decode(m.getBytes());

				xc.keyFinal(bytes);
	
				nextFilter.sessionCreated(session);
				nextFilter.sessionOpened(session);
				break;
				
			case STATE_MESSAGE:			
				m = decrypt(m, session);
				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.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
			SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
			throw new XCException(context.getAdapterName() + " | xecure error - " + e.getMessage() + " | " + xcMessage);
		}
	}	
}
