/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.ui.util;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionServlet;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.struts.ContextLoaderPlugIn;

import servletunit.struts.MockStrutsTestCase;

import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.id.PersonIdEntityKeyImpl;

import gov.va.med.esr.service.PersonService;

/**
 * @author Madhu Katikala (@user)
 */
public abstract class AbstractUITestCase extends MockStrutsTestCase {
    
	protected static Log log = LogFactory.getLog(AbstractUITestCase.class);

    //bean definition files
	protected static final String COMMON_CONTEXT = "commons/applicationContext.xml";
	protected static final String UI_CONTEXT = "ui/applicationContext.xml"; 
	protected static final String TEST_CONTEXT = "ui/test_components.xml";
    
    //Application Context
	protected static XmlWebApplicationContext ctx;
    
    //Test properties (data)
    protected static Properties testProperties;
    
    //Error message constants
    private static final String APP_CONTEXT_NOT_INITIALZED = 
        "Application context is not initialized: call super.setup()";

	/**
	 *  
	 */
	public AbstractUITestCase() {
		super();
	}

	/**
	 * @param arg0
	 */
	public AbstractUITestCase(String name) {
		super(name);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
		//set the default configuration parameters
		setServletConfigFile("web.xml"); //reads from classpath
		setInitParameter("validating", "false");
		loadApplicationContext(); //load application context (common/ui/test)
	}

	protected void loadApplicationContext() throws Exception{
		ActionServlet servlet = getActionServlet();
		ServletContext sCtx = servlet.getServletContext();

		//logAttributes("InitParameterNames: ", sCtx.getInitParameterNames());

		/*
		 * ConextLoader is not loading the context properly with test
		 * resources ??? ContextLoader contextLoader = new ContextLoader();
		 * contextLoader.initWebApplicationContext(sCtx);
		 */
		//application context is stored as static varaible to avoid loading
		// multiple times
		if (ctx == null) {
			ctx = new XmlWebApplicationContext();
			ctx.setConfigLocations(new String[] { COMMON_CONTEXT,
					UI_CONTEXT, TEST_CONTEXT });
		}
		ctx.setServletContext(sCtx);
		ctx.refresh();
		//set both root app context and plugin context
		sCtx.setAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX, ctx);
		sCtx.setAttribute(
			WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
			ctx);
        testProperties = (Properties) ctx.getBean("testProperties");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
	}

	/**
	 * Lists the attributes in the session and request
	 *  
	 */
	protected void verifySessionData() {
		Enumeration e = getSession().getAttributeNames();
		while (e.hasMoreElements())
			log.info("Session Attribute:" + e.nextElement());

		e = getRequest().getAttributeNames();
		while (e.hasMoreElements())
			log.info("Request Attribute:" + e.nextElement());

		//log application data keys
		Map appData = (Map) getSession().getAttribute("AppData");
		if (appData != null)
			log.info("AppData Keys: " + appData.keySet());
	}

	/**
	 * Utility methods to get the data from configuration files for testing
	 * the properties are defined in test.properties and included in test_resources.jar
	 */
	protected String getSearchFamilyName() {
		return getProperty("test.search.lastname", null);
	}

	protected String getSearchSSN() {
		return getProperty("test.search.ssn", null);
	}

	protected String getPersonId() {
		return getProperty("test.personid", null);
	}
    
    protected final String getProperty(String key, String defValue) {
        if (testProperties == null) {
            log.error("testProperties is not initialized");
            return null;
        } else {
            return testProperties.getProperty(key, defValue);
        }
    }
    
	protected final String getMessage(String key, Object[] substitutePars,
			String defValue) {
		if (ctx == null) {
			log.error("Application Context is not initialized");
			return null;
		} else
			return ctx.getMessage(key, substitutePars, defValue, null);
	}

	//service related utilitiy methods   
    public final PersonService getPersonService () throws Exception {
        if (ctx == null) {
        	throw new Exception (APP_CONTEXT_NOT_INITIALZED);
        }

    	return (PersonService) ctx.getBean("personService");
    }
    
    public final Person getPerson(String personId) throws Exception {
    	PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(personId);    	
    	return getPersonService().getPerson(personKey);
    }

	/**
	 * utility methods and variables to carry the data between tests
	 */
	protected static Map appData;
	protected static String seletedPersonId;
	protected static Person selectedPerson;
	protected static Person updatedPerson;

	protected String getSelectedPersonId() {
		return seletedPersonId;
	}

	protected void setSelectedPersonId(String id) {
		AbstractUITestCase.seletedPersonId = id;
	}

	protected static Person getSelectedPerson() {
		return selectedPerson;
	}

	protected static void setSelectedPerson(Person selectedPerson) {
		AbstractUITestCase.selectedPerson = selectedPerson;
	}

	protected static Person getUpdatedPerson() {
		return updatedPerson;
	}

	protected static void setUpdatedPerson(Person updatedPerson) {
		AbstractUITestCase.updatedPerson = updatedPerson;
	}
	protected static void setAppData (Map appDataMap) {
		appData = appDataMap;
    }
    protected static Map getAppData () {
        if (appData == null)
            appData = new HashMap ();
    	return appData;
    }
	protected void loadAppData() {
		getSession().setAttribute("AppData", getAppData());
	}

	protected void saveAppData() {
		appData = (Map) getSession().getAttribute("AppData");
	}
}