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

import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
import com.eactive.eai.common.util.Logger;
import org.apache.mina.common.IoFilterAdapter;
import org.apache.mina.common.IoFilterChain;
import org.apache.mina.common.IoSession;
import tcseed.tcseed;

public abstract class TcseedFilter extends IoFilterAdapter {
	protected final Logger logger;
	protected final Logger errLogger;

	private static final String NEXT_FILTER = TcseedFilter.class.getName() + ".NextFilter";
	protected static final String FILTER_STATE_KEY = TcseedFilter.class.getName() + ".STATE";
	protected static final String SESSION_STATE = "SESSION_STATE";

	protected enum State {
		STATE_HANDSHAKE,
		STATE_MESSAGE;
	}
	
	protected static class FilterState {
		public State  state = State.STATE_MESSAGE;
	}
	
    protected SocketAdapterContext context;
	protected ISocketAdapter adapter;
	
	protected tcseed ts = new tcseed();
	
	protected TcseedFilter(ISocketAdapter adapter) {
		this.adapter = adapter;
		this.context = adapter.getContext();

	    logger    = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
	    errLogger = SocketLoggerManager.getInstance().getErrLogger();
		
		/**
		 * tcseed init
		 */
		ts.Init_Key(context.getTcseedKeyStore());		    
	}

	@Override
	public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
		if (parent.contains(TcseedFilter.class)) {
			throw new IllegalStateException("A filter chain cannot contain more than one DesFilter.");
		}
		
		IoSession session = parent.getSession();
		session.setAttribute(NEXT_FILTER, nextFilter);
	}
	
	@Override
	public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
		FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);

		if (filterState == null) {
			filterState = new FilterState();
			session.setAttribute(FILTER_STATE_KEY, filterState);
		}
		    
		nextFilter.sessionCreated(session);
	}	

	
	@Override
    public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
		FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
		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");
		}

		if (filterState.state == State.STATE_MESSAGE) {
	        byte[] encrypted = ts.Encrypt(m.getBytes());
	        m = new ByteMessage(encrypted);
	    }
		
		/**
		 * next filter
		 */
		nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
    }
	
	protected void setSessionState(IoSession session, String state) {
		session.setAttribute(SESSION_STATE, state);
	}
}
