package gov.va.med.authentication.kernel.ccow;

import gov.va.med.authentication.kernel.KaajeeException;
import gov.va.med.authentication.kernel.LoginUserInfoVO;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;

import org.apache.log4j.Logger;
import org.apache.log4j.Level;

/**
 * @author VHIT Security and Other Common Services (S&OCS)
 * @version 1.1.0.007
 */
public class ContextInitializerFilter implements Filter {
	
	private static Logger logger = Logger.getLogger(ContextInitializerFilter.class);

	public static String CONTEXT_PARTICIPANT = "ccowcp";
	public static String APPLET_CODEBASE = "applets/";
	public static String CCOW_KAAJEE_APPL_NAME = "VistaLinkLoginModule";
	public static String SESSION_ID = "kaajeeJSESSIONID";
    public static String APP_ARCHIVE_J2 = "WebJ2Applets.jar";
    public static String APP_ARCHIVE_IE = "WebIEApplets.cab";
	public static boolean UseIETag = false;
	public static String APP_LOCATE_TIMEOUT = "60";
	public static String LOCATOR_APPLET_BODY = "loading CCOW locator applet . . . .";
	public static String APP_DEBUG =  "debug";

    
	public void init(FilterConfig config) throws ServletException {
		
		CONTEXT_PARTICIPANT = config.getInitParameter("context-participant");
		APPLET_CODEBASE = config.getInitParameter("applet-codebase");
		CCOW_KAAJEE_APPL_NAME = config.getInitParameter("ccow-kaajee-appl-name");
		SESSION_ID = config.getInitParameter("session-id");
		APP_ARCHIVE_J2 = config.getInitParameter("app-archive-J2");
		APP_ARCHIVE_IE = config.getInitParameter("app-archive-IE");
		UseIETag = Boolean.valueOf(config.getInitParameter("UseIETag")).booleanValue();
		APP_LOCATE_TIMEOUT = config.getInitParameter("app-locate-timeout");
		LOCATOR_APPLET_BODY = config.getInitParameter("locator-applet-body");
		APP_DEBUG = config.getInitParameter("app-debug");
	}

	/*
	 *  filters on the status of the contextor running
	 *  it should be the first filter in the chain so that a Locator applet is returned
	 */
	public void doFilter(ServletRequest servletReq, ServletResponse servletResp,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest req = (HttpServletRequest)servletReq;
		HttpServletResponse res = (HttpServletResponse)servletResp;
		
		// must create a new session object as it is needed to initialize ccow contextor
		req.getSession(true);
		CcowEnv ccowEnv = CcowEnv.getInstance(req);		
		ContextInitializer initializer = new ContextInitializer(ccowEnv, req, res);
        LoginDispatcher dispatcher = new LoginDispatcher(ccowEnv, req, res);
        
		if (initializer.isUserLoggedIn()) {
			// already logged in, ignore and continue
			dispatcher.continueChain(servletReq, servletResp, chain);
			return;
		}
		
        if (!initializer.locatorSent()) {
        	// locator applet hasn't been sent
        	// initialize the ccow environment and 
        	// send locator applet ONCE to redirect the browser
        	initializeEnvironment(initializer);
        	return; // must return as a redirect has occurred
        }        
        // locator applet has been sent, continue
        
        if ( initializer.detectedCtxMgrParam() ) {  
    		// join context
    		joinCommonContext(initializer);
    	}
    	// check for any existing user context and validate it
        VistaTokenValidator validator = new VistaTokenValidator(ccowEnv);
        
    	if (validator.hasVAContext()) {
    		try {
    			LoginUserInfoVO userInfo = validator.validate();
    			ccowEnv.setLoginUserInfo(userInfo);
    			ccowEnv.setLoginUsingToken();
    			// already authenticated user, forwarded to LoginController, no more processing here.
    			dispatcher.forwardToLoginController(userInfo);
    			return;
			} catch (KaajeeException e) {
				// validation failed or could not forward to LoginController
				if (logger.isEnabledFor(Level.ERROR)) {
					logger.debug("failed to validate existing user context or to forward to LoginController:"  + e);
				}
				// clean up
				suspendContext(ccowEnv);
			}    		
    	} else {
    		// clean up
    		suspendContext(ccowEnv);
    	}
    	// continue on to the requested page (login page)
    	dispatcher.continueChain(servletReq, servletResp, chain);
    	return;
	}

	private void initializeEnvironment(ContextInitializer initializer) {
		
		if (logger.isEnabledFor(Level.DEBUG)) {
			logger.debug("initializing ccow environment . . . ");
		}
    	//initialize the ccow environment for this web application
    	initializer.setEnvironment();
    	
		if (logger.isEnabledFor(Level.DEBUG)) {
			logger.debug("sending locator applet . . . ");
		}
    	// send locator applet ONCE to redirect the browser
    	// to the same url; so this filter will be checked again
    	initializer.sendLocatorApplet();
    	return; // must return as a redirect has occurred
	}
	
    private void joinCommonContext(ContextInitializer initializer) {
		if (logger.isEnabledFor(Level.DEBUG)) {
			logger.debug("joining Context using initializer: ");
		}
		
		initializer.joincontext();
		
		
		if (logger.isEnabledFor(Level.DEBUG)) {
			logger.debug("retrieving VA context: ");
		}

		initializer.retrieveUserContext();
	}

	private void suspendContext(CcowEnv ccowEnv) {
		
		if (logger.isEnabledFor(Level.DEBUG)) {
			logger.debug("Suspending temporary read Context");
		}

		ContextManager.suspendContext(ccowEnv);
		ccowEnv.setNotLoginUsingToken();
	}
	
	public void destroy() {
		// TODO Auto-generated method stub

	}
}
