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 com.eactive.eai.util.IpUtil;

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 AclFilter extends IoFilterAdapter {
	final protected Logger logger;
    final protected Logger errLogger;

    protected SocketAdapterContext context;
	protected ISocketAdapter adapter;

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

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

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

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

		session.close();
    }

    private boolean isAllowed(IoSession session) {
		SocketAddress remoteAddress = session.getRemoteAddress();
        
        if (remoteAddress instanceof InetSocketAddress) {
        	byte[] remoteAddr = ((InetSocketAddress) remoteAddress).getAddress().getAddress();
        	String remoteIp = "";
        	for (int i=0; i<remoteAddr.length; i++) {
        		if (i > 0) {
        			remoteIp += ".";
        		}
        		remoteIp += remoteAddr[i]&0xFF;
        	}
        	return IpUtil.isMatchIp(String.join(",", aclList), remoteIp);
        }

        return false;
    }
}
