package com.eactive.eai.adapter.socket2.filter.acl;

import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
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.IoSession;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class L4SkipIpFilter extends IoFilterAdapter {
	final protected Logger logger;
    final protected Logger errLogger;

    protected SocketAdapterContext context;
	protected ISocketAdapter adapter;

	private final Set<String> l4SkipIpList = new HashSet<String>();
	
	public L4SkipIpFilter(ISocketAdapter adapter) {
		this.adapter = adapter;
		this.context = adapter.getContext();

	    logger    = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
	    errLogger = SocketLoggerManager.getInstance().getErrLogger();
	    
	    String[] l4SkipList = context.getL4SkipIpList().split(",");
	    for (int i=0; i<l4SkipList.length; i++) {
	    	l4SkipIpList.add(l4SkipList[i].trim());
	    }
	}	    

    public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
        if (isSkiped(session)) {
        	blockSession(session);
        } else {
        	nextFilter.sessionOpened(session);
        }
    }

    public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
        if (isSkiped(session)) {
        	//blockSession(session);
        } else {
        	nextFilter.sessionClosed(session);
        }
    }
    
    private void blockSession(IoSession session) {
		if (context.getTraceLevel() >= context.TRACE_LEVEL_INFO) {
			logger.info(context.getAdapterName() + " | L4SkipFilter | "+context.getL4SkipIpList()+" | deny connection - [" + session.toString() + "]");
		}
//		session.close();
    }

    private boolean isSkiped(IoSession session) {
		SocketAddress remoteAddress = session.getRemoteAddress();
        
        if (remoteAddress instanceof InetSocketAddress) {
        	for (String allow : l4SkipIpList) {
	            byte[] remoteAddr = ((InetSocketAddress) remoteAddress).getAddress().getAddress();
	            String remoteIp = "";
	            for (int i=0; i<remoteAddr.length; i++) {
	                if (i > 0) {
	                	remoteIp += ".";
	                }
	                remoteIp += remoteAddr[i]&0xFF;
	            }
	            
	            if (allow.indexOf('*') == -1) {          	
	            	if (allow.equals(remoteIp)) {
	            		return true;
	            	}
	            } else {
					String allowRegexp = allow.replaceAll("\\*", "[0-9]+");
					Matcher matcher = Pattern.compile(allowRegexp, Pattern.CASE_INSENSITIVE).matcher(remoteIp);
					if (matcher.matches()) {
						return true;
					}
	            }
        	}
        }

        return false;
    }
}
