package com.eactive.eai.adapter.socket2.protocol.login.handshake;

import com.eactive.eai.adapter.socket2.common.CommonLib;
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 org.apache.mina.common.IoSession;


public class LoginClientFilter extends LoginFilter {
	public LoginClientFilter(ISocketAdapter adapter) {
		super(adapter);
	}	

	
	@Override
    public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
		process(nextFilter, session, null);
	}
	
	@Override
	public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
		ByteMessage m = (ByteMessage) message;		
		process(nextFilter, session, m);
	}	
	
	protected void process(NextFilter nextFilter, IoSession session, ByteMessage message) throws Exception {
		try {
			FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
			if (filterState == null) {
				filterState = new FilterState();
				session.setAttribute(FILTER_STATE_KEY, filterState);
			}
			/**
			 * State machine
			 */
//			ByteBuffer buffer = null;
			
			switch (filterState.state) {
			case STATE_LOGIN_SEND:
				
				
//				session.getRemoteAddress()
				
				/**
				 * change state to SEND
				 */
				filterState.state = State.STATE_LOGIN_SEND;
				session.setAttribute(SESSION_STATE, filterState.state.toString());

				/**
				 * create send data
				 */
				ByteMessage data = getHexToByte(context.getLoginSend());
		        
				if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
					logger.debug(context.getAdapterName() + " | LoginClientFilter | <SEND> LOGIN_SEND" + CommonLib.hexDump(data.getBytes(), true, context));
				}
				session.write(data.getBytes());
				
				/**
				 * change state to UPDATE
				 */
				filterState.state = State.STATE_LOGIN_RECV;
				setSessionState(session, filterState.state.toString());
				break;
				
			case STATE_LOGIN_RECV:
				if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
					logger.debug(context.getAdapterName() + " | LoginClientFilter | <RECV> LOGIN_RECV response");
				}
				/**
				 * recv data comp
				 */	
				byte[] recv = null;
				
				if(message == null) {
					session.close();
					throw new Exception("<RECV> invalid message during handshake .. : " + message);
				}
				else {
					recv = message.getBytes();
				}

				
				ByteMessage loginRecv = getHexToByte(context.getLoginRecv());
				
				if (!new String(recv).startsWith(loginRecv.getString()) ){
					session.close();
					throw new Exception("<RECV> invalid message during handshake .. : " + message);
				}
				
				/**
				 * change state
				 */
				filterState.state = State.STATE_MESSAGE;
				setSessionState(session, filterState.state.toString());	

				/**
				 * finish handshake
				 */
				if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
					adapter.addRecentLog(context.getAdapterName() + " | LoginClientFilter | handshake finished ...");
					logger.debug(context.getAdapterName() + " | LoginClientFilter | handshake finished ...");
				}	
				
				nextFilter.sessionCreated(session);
				nextFilter.sessionOpened(session);

				break;
				
			case STATE_MESSAGE:			
				nextFilter.messageReceived(session, message);
				break;
				
			default:
				throw new Exception("<RECV> invalid message during handshake .. : " + message);
			}
		} catch(Exception e) {
			adapter.addRecentError(context.getAdapterName() + " | login error - " + e.getMessage(), e);
			logger.error(context.getAdapterName() + " | login error - " + e.getMessage(), e);
			errLogger.error(context.getAdapterName() + " | login error - " + e.getMessage(), e);
			SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
			throw new Exception(context.getAdapterName() + " | login error - " + e.getMessage(), e);
		}
	}	

	private ByteMessage getHexToByte(String line){
		ByteMessage data = new ByteMessage();
		while(line.indexOf("0x") != -1) {
				data.append(line.substring(0, line.indexOf("0x")));
				String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);	
				data.append((byte) Integer.parseInt(hex.substring(2), 16));
				line = line.substring(line.indexOf("0x")+4);				
		}
		data.append(line);
		return data;

	}
}
