/********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/

package gov.va.med.esr.service.external;

import gov.va.med.esr.common.model.security.EEServiceRequestLite;
import gov.va.med.esr.common.model.security.EEServiceUser;
import gov.va.med.esr.common.model.security.EEServiceUserRequest;
import gov.va.med.esr.service.EEServiceAdminService;
import gov.va.med.esr.service.trigger.CommonTrigger;
import gov.va.med.esr.service.trigger.CommonTriggerEvent;
import gov.va.med.esr.service.trigger.CommonTriggerIdentity;
import gov.va.med.esr.service.trigger.CommonTrigger.DestinationType;
import gov.va.med.fw.security.LoginManager;
import gov.va.med.fw.security.UserCredentials;
import gov.va.med.fw.service.ConfigurationConstants;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.trigger.PublishTriggerableService;

import java.io.Serializable;
import java.util.Iterator;
import java.util.Set;

import javax.ejb.CreateException;
import javax.ejb.SessionContext;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.security.auth.login.LoginException;

import org.apache.commons.lang.ClassUtils;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.ejb.support.AbstractStatelessSessionBean;
import org.springframework.web.context.ContextLoader;

/**
 * Initial javadoc for class ExternalServiceBean. TODO - Add content here
 * 
 * Created Jan 4, 2006 9:55:09 AM
 * 
 * @author DNS   BOHMEG
 */
public class ExternalServiceBean extends AbstractStatelessSessionBean {
	private static final long serialVersionUID = 7991017815476094540L;

    private static DestinationType DEFAULT_DESTINATION_TYPE = CommonTrigger.DestinationType.COMMON;
	
	// used in env-entry
	public static final String FACTORY_LOCATOR_SELECTOR = ContextLoader.LOCATOR_FACTORY_SELECTOR_PARAM;

	public static final String FACTORY_LOCATOR_KEY = "locatorFactoryKey";

	private PublishTriggerableService publisher;
	private LoginManager loginManager;
	private EEServiceAdminService eeServiceAdminService;
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.ejb.support.AbstractStatelessSessionBean#onEjbCreate()
	 */
	protected void onEjbCreate() throws CreateException {
		publisher = (PublishTriggerableService) getBeanFactory().getBean(
				ClassUtils.getShortClassName(PublishTriggerableService.class), PublishTriggerableService.class);
	}

	public void setSessionContext(SessionContext sessionContext) {
		super.setSessionContext(sessionContext);
		setBeanFactoryLocator(ContextSingletonBeanFactoryLocator
				.getInstance(getEnvEntry(FACTORY_LOCATOR_SELECTOR)));
		setBeanFactoryLocatorKey(getEnvEntry(FACTORY_LOCATOR_KEY));
	}

	protected String getEnvEntry(String key) {
		String envEntry = null;

		try {
			Context ctx = new InitialContext();
			envEntry = (String) ctx.lookup(ConfigurationConstants.JAVA_ENV
					+ key);
			if (logger.isInfoEnabled()) {
				logger.info("Using EnvEntry: " + envEntry);
			}
		} catch (Exception e) {
			throw new RuntimeException("Failed to get Environment Entry for: "
					+ key, e);
		}

		return envEntry;
	}

	/**
	 * @return Returns the publisher.
	 */
	protected PublishTriggerableService getPublisher() {
		return publisher;
	}
	
	protected void processAuthenticate(String logicalID) throws LoginException {
		UserCredentials creds = new UserCredentials();
		creds.setAnonymous(true);
		creds.setLogicalID(logicalID);
		
		processAuthenticate(creds);
	}
	
	protected void processAuthenticate(UserCredentials cred) throws LoginException {
		if(cred != null && cred.isAnonymous())
			getLoginManager().loginAnonymous(cred.getLogicalID());
		else {
			// ensure Context is non-null for this Thread
			getLoginManager().loginAnonymous();
		}
		
		// now that context is non-null for this Thread, if cred exists, use it
		if(cred != null && !cred.isAnonymous())
			getLoginManager().login(cred);
	}

	protected void processAuthorize(String accountName, String requestName) throws 
							ServiceException, ESRException{
		EEServiceUser account = getEEAdminService().getEEServiceUser(accountName);
		Set requests = account.getEeServiceUserRequests();
		
		boolean foundRequest = false;
		
		if ( requests != null && requests.size() > 0 ) {
			Iterator requestItr = requests.iterator();
			while(requestItr.hasNext() ) {
				EEServiceUserRequest userRequest = (EEServiceUserRequest)requestItr.next();
				EEServiceRequestLite req = userRequest.getEeServiceRequestLite();
				if (req.getName().equalsIgnoreCase(requestName) ) {
					foundRequest = true;
					break;
				}
			}
				
		}
		
		if (! foundRequest ) {
			throw new ESRException("Authorization exception. requestName not found:" +requestName);
		}
		
	}
	
	
	private LoginManager getLoginManager() {
		if (loginManager == null) {
			loginManager = (LoginManager) BeanFactoryUtils
					.beanOfTypeIncludingAncestors(
							(ListableBeanFactory) getBeanFactory(),
							LoginManager.class);
		}
		return loginManager;
	}	
	
	protected EEServiceAdminService getEEAdminService() {
		if (eeServiceAdminService == null) {
			eeServiceAdminService = (EEServiceAdminService) BeanFactoryUtils
					.beanOfTypeIncludingAncestors(
							(ListableBeanFactory) getBeanFactory(),
							EEServiceAdminService.class);
		}
		return eeServiceAdminService;
		
	}
	
	protected void publishExternalEventForInternalProcessing(String name, Serializable payload) throws ServiceException {
		publisher.publishTriggerEvent(new CommonTriggerEvent(name, payload,
				new CommonTriggerIdentity(DEFAULT_DESTINATION_TYPE)));
	}
}
