/*******************************************************************************
/*******************************************************************************
 * Copyright � 2004-2005 VHA. All rights reserved
 ******************************************************************************/
package gov.va.med.esr.ui.admin.action;

// Java Classes
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.ee.Application;
import gov.va.med.esr.common.model.ee.EligibilityVerification;
import gov.va.med.esr.common.model.ee.EnrollmentDetermination;
import gov.va.med.esr.common.model.lookup.AddressType;
import gov.va.med.esr.common.model.lookup.ApplicationMethod;
import gov.va.med.esr.common.model.lookup.SSAVerificationStatus;
import gov.va.med.esr.common.model.lookup.ApplicationStatus;
import gov.va.med.esr.common.model.lookup.Country;
import gov.va.med.esr.common.model.lookup.EligibilityStatus;
import gov.va.med.esr.common.model.lookup.Gender;
import gov.va.med.esr.common.model.lookup.NameType;
import gov.va.med.esr.common.model.lookup.PhoneType;
import gov.va.med.esr.common.model.lookup.SSAVerificationStatus;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.party.Phone;
import gov.va.med.esr.common.model.person.Association;
import gov.va.med.esr.common.model.person.BirthRecord;
import gov.va.med.esr.common.model.person.EnrollmentApplication;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.common.model.person.id.PersonEntityKey;
import gov.va.med.esr.common.model.person.id.VPIDEntityKey;
import gov.va.med.esr.common.model.person.id.VPIDEntityKeyImpl;
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.service.IdmServiceVO;
import gov.va.med.esr.service.PersonIdentityTraits;
import gov.va.med.esr.ui.ApplicationConstants;
import gov.va.med.esr.ui.admin.beans.VeteranSearchBean;
import gov.va.med.esr.ui.common.action.PersonAbstractAction;
import gov.va.med.esr.ui.conversion.UIConversionService;
import gov.va.med.esr.ui.util.ConvertUtils;
import gov.va.med.esr.ui.util.MockPersonBuilder;
import gov.va.med.esr.ui.util.SessionManager;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.ui.UIConstants;
import gov.va.med.fw.ui.struts.ValueListActionUtils;
import gov.va.med.fw.ui.valuelist.InvalidArgumentValueListException;
import gov.va.med.fw.ui.valuelist.MaxRecordsExceededValueListException;
import gov.va.med.fw.ui.valuelist.MissingCapabilityValueListException;
import gov.va.med.fw.ui.valuelist.SearchValueListAdapter;
import gov.va.med.fw.ui.valuelist.TimeoutValueListException;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.validation.ValidationMessage;
import gov.va.med.fw.validation.ValidationMessages;
import gov.va.med.fw.validation.ValidationServiceException;
import gov.va.med.esr.service.MessagingService;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.mlw.vlh.ValueList;
import net.mlw.vlh.ValueListInfo;

import org.apache.commons.lang.Validate;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

/**
 * Struts action class that will perform person searches using the ValueList infrastructure.
 *
 * @author Andrew Pach
 * @version: 3.0
 */
public class SearchAction extends PersonAbstractAction
{
    /**
     * Debug flag that causes a mock person to be retrieved when set.
     */
    public static final String USE_MOCK_DEBUG_FLAG = "ui.use.mock.person";

    /**
     * Debug flag that causes a mock person to be created in the database when set.
     */
    public static final String CREATE_MOCK_DEBUG_FLAG = "ui.create.mock.person";

    public static final String ADDAPERSON_INFO_MESSAGE = "message.addAPersonInfo";

    // The mock person builder class
    private MockPersonBuilder mockPersonBuilder = null;

    // Forwards
    public static final String PERSON_OVERVIEW = "overview";

    // CodeCR10471_WS_Add a Person Record capability to ESR
    public static final String FORWARD_DISPLAY_NEW = "displayNew";
    public static final String FORWARD_DISPLAY_STATUS_HISTORY = "displayStatusHistory";

    //Default country to USA if country is not selected as part of Add person through AAP screen - ESR_CodeCR13036
    public static final String USA = "USA";

    /**
     * A default constructor
     */
    public SearchAction()
    {
        super();
    }

    /**
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    public void afterPropertiesSet() throws Exception
    {
        if (getMockPersonBuilder() == null)
        {
            if (log.isWarnEnabled())
            {
                log.warn("Mock person builder is not set.  This should be set when using the mock debug flag.");
            }
        }
    }

    /**
     * Displays the search screen.
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception if any errors occurred while trying to select the person.
     */
    public ActionForward display(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        // Clear the search form
        SearchActionForm searchForm = (SearchActionForm)form;
        searchForm.clear();

        // CR 10471 Add a Person to turn off the Add A Person flag
        putSandboxEntry(request, ApplicationConstants.SessionData.ADD_A_PERSON, new Boolean(false));

        // Forward to the overview screen
        return mapping.findForward(UIConstants.SUCCESS);
    }

    /**
     * Save the person into DB which is still in process
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception if any errors occurred while trying to select the person.
     */
    public ActionForward saveInProcess(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
    	try {
    		// If not add a person, then get out of here
    		boolean isAddAPerson = SessionManager.isAddAPerson(request);
    		if (!isAddAPerson) {
    			return mapping.findForward(PERSON_OVERVIEW);
    		}

    		// Ensure we have a valid search form
    		SearchActionForm searchForm = (form instanceof SearchActionForm) ? (SearchActionForm)form : null;
    		Validate.notNull(searchForm, "SearchActionForm bean is null");

    		Person person = getSelectedPerson(request);

    		// Persist the new person in process

    		this.getApplicationInProcessService().savePersonInProcess(person,
    				this.getLookupService().getApplicationStatusByCode(
        					ApplicationStatus.IN_PROCESS.getCode()));
    	} catch (Exception e) {
    		addActionMessage(request, "error.addPerson", e.toString());
    		logger.error(e.toString());
    	}
    	return mapping.findForward(PERSON_OVERVIEW);
    }

    /**
     * Cancel Registration
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception if any errors occurred while trying to select the person.
     */
    public ActionForward cancelRegistration(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
       	try {
    		// If not add a person, then get out of here
    		boolean isAddAPerson = SessionManager.isAddAPerson(request);
    		if (isAddAPerson) {
	     		// Ensure we have a valid search form
	    		SearchActionForm searchForm = (form instanceof SearchActionForm) ? (SearchActionForm)form : null;
	    		Validate.notNull(searchForm, "SearchActionForm bean is null");

	    		Person person = getSelectedPerson(request);

	    		// Clear the previous search person, form and disable add button
	    		removeSelectedPerson(request);
	    		searchForm.clear();
	    		searchForm.setAddButtonDisabled(true);
	    		// Update the person's application status

	    		this.getApplicationInProcessService().savePersonInProcess(person,
	    				this.getLookupService().getApplicationStatusByCode(
	        					ApplicationStatus.CANCEL.getCode()));
    		}
    	} catch (Exception e) {
    		addActionMessage(request, "error.addPerson", e.toString());
    		logger.error(e.toString());
    	}
        // Forward to the overview screen
        return mapping.findForward(FORWARD_DISPLAY_NEW);
    }

    /**
     * Displays the search and add new person screen.
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception if any errors occurred while trying to select the person.
     */
    public ActionForward displayNew(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        // Clear the search form
        SearchActionForm searchForm = (SearchActionForm)form;
        searchForm.setAddButtonDisabled(true);
        searchForm.clear();

        // Check system flag to see if MVI has implemented Self-Identified Gender Identity
        // This will determine if the SIGI dropdown is hidden or not on the screen
        Boolean isSigiAvailable = super.getSystemParameterService().getEsSidIndicator();
        searchForm.setDisableSelfIdentifiedGenderIdentity(isSigiAvailable);

        // Turn on the Add A Person flag
        putSandboxEntry(request, ApplicationConstants.SessionData.ADD_A_PERSON, new Boolean(true));

        //clear the previously retrieved person
        removeSelectedPerson(request);

        // Forward to the overview screen
        return mapping.findForward(FORWARD_DISPLAY_NEW);
    }

    /**
     * Displays the search new person screen.
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception if any errors occurred while trying to select the person.
     */
    public ActionForward displayStatusHistory(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
    	//Clear the search form
        SearchActionForm searchForm = (SearchActionForm)form;
        searchForm.clear();

        ActionForward forward = mapping.findForward(FORWARD_DISPLAY_STATUS_HISTORY);

        Person person = getSelectedPerson(request);

        if (person == null) {
        	// In process Registration and Enrollment
    		addActionMessage(request, "error.addPerson", "Person not selected for displaying status history!");
    		forward = mapping.findForward(UIConstants.FAILURE);
     	}
        else{
        	String vpidVaue = person.getVPIDEntityKey().getShortVPID();
        	EnrollmentApplication ea = getApplicationInProcessService().getEnrollmentApplicationByIcn(vpidVaue);
        	UIConversionService uiConversionService = (UIConversionService)conversionService;
        	uiConversionService.convert(ea,searchForm);
        }

        return forward;
    }

    /**
     * Method to add new person. Send request to IdM to Add A person. IdM will return ICN (VPID). Enter Registration Screen
     * @param mapping
     * @param form
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public ActionForward addNewPersonScreen(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception
        {
    	SearchActionForm searchForm = (form instanceof SearchActionForm) ? (SearchActionForm)form : null;

        Validate.notNull(searchForm, "SearchActionForm bean is null");

    	//CCR12712 prevent duplicate Add person submissions
    	if (this.isTokenValid(request)) {
	    	this.resetToken(request);

	    	IdmServiceVO idmServiceVO = null;
			Person person = null;
			VPIDEntityKey vpid = null;
	        try{
	        	/*
	        	 * No IDM result,
				not in ADR Person table -
				We have a person object from search form input
				Request idm to add person, this will automatically add ESR200 correlation
				Create a stub record in Enrollment _application table
				Allow the user continue with the registration
				*/

	        	//CCR12712 prevent duplicate Add person submissions
	        	//check at request time that there is not already an exact match
	        	ValueList valueList = ValueListActionUtils.getValueList(searchForm,
	                    request, "personSearchTableId", "personSearchAdapter");

	        	List results = valueList.getList();

	        	if (results != null && !results.isEmpty()) {
	        		for (Iterator iter = results.iterator(); iter.hasNext();)
	                    {
	                    	VeteranSearchBean veteranBean = (VeteranSearchBean)iter.next();
	                        if(veteranBean.getIdmMatchTypeValue().equals("Yes")){

	                        	vpid = CommonEntityKeyFactory.createVPIDEntityKey(veteranBean.getVpid());
	                        }
	                    }

	        	}


	        	idmServiceVO = this.createIdmServiceVO((SearchActionForm)form);

	        	// Request idm to add person, this will automatically add ESR200 correlation
	        	if (vpid == null) {
	        		vpid = getPersonService().addPerson(idmServiceVO);
	        	} else {
	        		person = this.convertIdmServiceVOToPerson(idmServiceVO, vpid);
	        		getPersonService().addESRCorrelation(person);
	        	}


	        	// Create new person from search form input fields
	        	person = this.convertIdmServiceVOToPerson(idmServiceVO, vpid);

	            // get the ESR person's personKey:
	            PersonEntityKey personKey = getPersonService().getPersonIdByVPID(vpid);

	            if (personKey == null) {
	            	throw new ServiceException("Unable to getPerson Id by vpid added by idmService: " + vpid.getKeyValueAsString());
	            }

	            // take the identity traits from idm and copy into in-process person
	            //CCR13415 - do not retrieve newly seeded person
	            //Person onFilePerson = getPersonService().getPerson(personKey);

	            // Set the personId to be saved in-process
	            person.setIdentifier(personKey.getKeyValue());

	            // Also set identity traits
	            //CCR13415
	            //person.setIdentityTraits(onFilePerson.getIdentityTraits());

	            // Copy the address from the from to the person
	            addDefaultValues(person, (SearchActionForm)form);

	            // Create a stub record in Enrollment _application table
	            getApplicationInProcessService().savePersonInProcess(person,
	            		this.getLookupService().getApplicationStatusByCode(
						ApplicationStatus.NEW_APPLICATION.getCode()));
			}
			catch (ValidationServiceException ex){

				ValidationMessages mesg = ex.getValidationMessages();
				Iterator  mesgItr = mesg.get();
				while (mesgItr.hasNext()){
					ValidationMessage msgObj= (ValidationMessage)mesgItr.next();
					addActionMessage(request, new ActionMessage(msgObj.getKey()));
	    		}
			}

			setSelectedPerson(request, person);

    	} else {
    		//CCR12712 prevent duplicate Add person submissions
    		//forward them back to search screen to select person already added

            searchForm.setAddButtonDisabled(true);

            // Turn on the Add A Person flag
            putSandboxEntry(request, ApplicationConstants.SessionData.ADD_A_PERSON, new Boolean(true));

            //clear the previously retrieved person
            removeSelectedPerson(request);
            addActionMessage(request, 	"error.duplicateAddPerson");

            //forward back to AAP search with err msg
            return mapping.findForward(FORWARD_DISPLAY_NEW);
    	}
    	// Forward to the person overview screen
    	return mapping.findForward(this.PERSON_OVERVIEW);
    }

    /**
     * Performs a person search based on the search criteria entered by the user.
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception if any errors occurred while trying to process the person search.
     */
    public ActionForward search(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        // ActionForward that defines where we will forward to next
        ActionForward forward = null;

        // Ensure we have a valid search form
        SearchActionForm searchForm = (form instanceof SearchActionForm) ? (SearchActionForm)form : null;
        Validate.notNull(searchForm, "SearchActionForm bean is null");

        boolean isAddAPerson = SessionManager.isAddAPerson(request);
        searchForm.setAddAPerson(isAddAPerson);

        try
        {
            // Mock retrieval can be used for developers
            if (isMockPersonRetrieveEnabled())
            {
                // Retrieve the person
                // (pass in the last name field which contains an optional person Id to retrieve)
                retrievePerson(searchForm.getFamilyName(), request);

                // Forward to the overview screen
                return mapping.findForward(PERSON_OVERVIEW);
            }

            // ***** REVISIT *****
            // We might want to inject the table id and the adapter name instead of
            // hard coding it here

            // Get the value list information
            ValueList valueList = ValueListActionUtils.getValueList(searchForm,
                request, "personSearchTableId", "personSearchAdapter");

            // Check if any results were found
            ValueListInfo info = valueList.getValueListInfo();
            if (info.getTotalNumberOfEntries() == 0)
            {
                // Clear the search form
                //searchForm.clear();
                searchForm.setAddButtonDisabled(false);

                //CCR12712 prevent duplicate Add person submissions
                //Add request token only valid after we've searched and explicitly enabled the button
                this.saveToken(request);

                // No results were found so generate an error and forward to the
                // failure page
                addActionMessage(request, new ActionMessage(
                    ApplicationConstants.MessageKeys.ERRORS_SEARCH_NORESULT));
                forward = (SessionManager.isAddAPerson(request)) ?
                		mapping.findForward(FORWARD_DISPLAY_NEW) : mapping.findForward(UIConstants.FAILURE);
            }
            else
            {
            	List results = valueList.getList();

            	boolean toDisable = false;

            	if(results != null && !results.isEmpty())
                {
                    for(Iterator iter = results.iterator(); iter.hasNext();)
                    {
                    	VeteranSearchBean veteranBean = (VeteranSearchBean)iter.next();
                        if(veteranBean.getIdmMatchTypeValue().equals("Yes")){

                        	toDisable = true;
                        }
                    }
                }
            	// there are some hits in the search so disable the add button

            	// CCR10951 -- the ADD button must be enabled after the search is complete
            	// regardless of the number of records returned.
            	// searchForm.setAddButtonDisabled(true);
            	searchForm.setAddButtonDisabled(false);

            	//CCR12712 prevent duplicate Add person submissions
                //Add request token only valid after we've searched and explicitly enabled the button
            	if (toDisable == false) {
            		this.saveToken(request);
            	}

                if (info.getTotalNumberOfEntries() == 1)
                {
                // 1 result was found so automatically retrieve the person and forward to
				// the overview screen.
				//List results = valueList.getList();
				VeteranSearchBean veteranBean = (VeteranSearchBean)results.get(0);

				// CCR11593 Eliminate multiple 1305 search calls.  If a single row is returned from search,
				// the person traits should be saved into the session
				PersonIdentityTraits traits = getSelectedTraits(request);

				//CCR 10471 ADD A PERSON: make the locked person editable
				/* TODO: CR 10471 remove!
				if (SessionManager.isAddAPerson(request)){
					veteranBean.setPersonLockedReason(null);
					//System.out.println("SearchAction::search() isPersonLocked = " + veteranBean.isPersonLocked()
					//		+ "\nVeteranSearchBean =" + veteranBean);
				}  */
				if (!veteranBean.isPersonLocked() && !SessionManager.isAddAPerson(request))
				{
				    // Retrieve the person
				    retrievePerson(veteranBean.getPersonID(), request, traits);

				    // Forward to the overview page
				    forward = mapping.findForward(PERSON_OVERVIEW);
				}
             }

                if (forward == null)
                {
                    // Backup the ValueListInfo into session and store the resultant
                    // ValueList on the request
                    ValueListActionUtils.setValueList(request, valueList, "vlhlist");

                    // Forward to the success URL (i.e. display results)
                    if (SessionManager.isAddAPerson(request)) {
                    	//request.setAttribute(UIConstants.ADD_A_PERSON_BUTTON, new Boolean(true));

                       	// CCR10951 -- the ADD button must be enabled after the search is complete
                    	// regardless of the number of records returned.
                    	/*if (valueList.getList().size() == 0) {
                    		searchForm.setAddButtonDisabled(false);
                    	} else {
                    		searchForm.setAddButtonDisabled(true);
                    	}*/
                    	searchForm.setAddButtonDisabled(toDisable);

                    	forward = mapping.findForward(FORWARD_DISPLAY_NEW);
                    } else {
                    	forward = mapping.findForward(UIConstants.SUCCESS);
                    }
                }
            }
        }
        catch (MaxRecordsExceededValueListException ex)
        {
            // The search exceeded the maximum number of records allowed so generate the appropriate
            // error message.
            if ((ex.getTotalRecords() > 0) && (ex.getRecordLimit() > 0))
            {
                // We know both the total number of records that would have been returned as well
                // as the configured limit.
                addActionMessage(request, new ActionMessage(
                    ApplicationConstants.MessageKeys.ERRORS_MAX_RECORDS_EXCEEDED,
                    new Integer(ex.getTotalRecords()), new Integer(ex
                    .getRecordLimit())));
            }
            else
            {
                // We only know the configured limit
                if (ex.getRecordLimit() > 0)
                {
                    addActionMessage(request, new ActionMessage(
                        ApplicationConstants.MessageKeys.ERRORS_MAX_RECORDS_EXCEEDED_RECORD_LIMIT,
                        new Integer(ex.getRecordLimit())));
                }
                else
                {
                    // Provide a generic message
                    addActionMessage(request, new ActionMessage(
                        ApplicationConstants.MessageKeys.ERRORS_MAX_RECORDS_EXCEEDED_NO_PARAMS));
                }
            }

            // Forward back to the search screen
            forward = mapping.findForward(UIConstants.FAILURE);
        }
        catch (MissingCapabilityValueListException ex)
        {
            // The user is not permitted to perform this search
            addActionMessage(request, new ActionMessage(
                ApplicationConstants.MessageKeys.ERRORS_INVALID_SEARCH_PERMISSION));
            forward = mapping.findForward(UIConstants.FAILURE);
        }
        catch (TimeoutValueListException ex)
        {
            // The user is not permitted to perform this search
            addActionMessage(request, TIMEOUT_ERROR_KEY);
            forward = mapping.findForward(UIConstants.FAILURE);
        }
        catch (InvalidArgumentValueListException ex)
        {
            // The user entered an invalid argument.
            addActionMessage(request, INVALID_ARGUMENT_KEY);
            forward = mapping.findForward(UIConstants.FAILURE);
        }

        // Return the forward
        return forward;
    }

    /**
     * Selects a person based on the selected person Id.
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception if any errors occurred while trying to select the person.
     */
    public ActionForward selectPerson(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        // Ensure we have a valid search form
        SearchActionForm searchForm = (form instanceof SearchActionForm) ? (SearchActionForm)form : null;
        Validate.notNull(searchForm, "SearchActionForm bean is null.");

        boolean isAddAPerson = SessionManager.isAddAPerson(request);
		if (!isAddAPerson) {

            //get the selected person id from the parameter list
            String personId = searchForm.getSelectedPersonId();
            Validate.notNull(personId, "Selected person Id is null.");

            // Retrieve the person based on the selected Person Id
            retrievePerson(searchForm.getSelectedPersonId(), request);

            // Forward to the overview screen or another screen
            String forwardTo = request.getParameter(FWD_TO);
            return (StringUtils.isNotEmpty(forwardTo)) ? mapping.findForward(forwardTo) : mapping.findForward(PERSON_OVERVIEW);
        }
        else {
           	// CCR10471 -- logic for Add a Person
        	return selectForAddAPerson(mapping, searchForm, request, response);
        }
    }

    /**
     * Select a person for the Search a Person logic
     * @param mapping
     * @param searchForm
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    private ActionForward selectForAddAPerson(ActionMapping mapping, SearchActionForm searchForm,
            HttpServletRequest request, HttpServletResponse response) throws Exception
    {

        String longVpid = searchForm.getSelectedVpid();

        String shortVpid = VPIDEntityKeyImpl.getShortVPID(longVpid);


    	Validate.notNull(shortVpid, "Selected short vpidValue is null.");

    	// The Person we eventually put into the session may come from: ADR Person table; or the in-process person table; or the idm search result bean
    	Person sessionPerson = null;

    	// Retrieve the ESR person based on the selected vpid value;
    	Person esrPerson = getESRPersonByVPID(longVpid);
		EnrollmentDetermination enrollDet = (esrPerson == null) ? null : esrPerson.getEnrollmentDetermination();

		// Retrieve the in-process registration with status being New or In-Process
    	Person inProcessPerson = this.getApplicationInProcessService().getInProcessPersonByIcn(shortVpid);

		// In certain scenarios we may need to create a new in-process person from the idm search result
    	Person idmSearchResultPerson = null;
    	if (esrPerson == null || (enrollDet == null && inProcessPerson == null)) {
    		idmSearchResultPerson = createPersonFromSearchResult(request, shortVpid);
    	}

		// set default ActionForward (go to Add a Person overview page)
		ActionForward forward = mapping.findForward(PERSON_OVERVIEW);
		boolean shouldDisableAddPerson = false;

        if (esrPerson != null) {

        	this.getPersonService().addESRCorrelation(esrPerson);

        	/* In IDM, in ADR person_Table, In in-progress table with the status (new',in-progress) - you have a person object from the in-progress table ,
					You will check the enrollment determination table
         		If no rows found in enrollment table, user can continue registration
         		If rows found in enrollment table, display a warning message and the user can only cancel.
              */
        	 if (inProcessPerson != null) {
        		sessionPerson = inProcessPerson;

        		if (enrollDet != null) {
                	// In process Registration and Enrollment
        			//automatically cancel the person's registration:
        			this.getApplicationInProcessService().savePersonInProcess(inProcessPerson,
    	    				this.getLookupService().getApplicationStatusByCode(
    	        					ApplicationStatus.CANCEL.getCode()));


        			addInformationMessage(request, ADDAPERSON_INFO_MESSAGE);
        			sessionPerson = esrPerson;
        			shouldDisableAddPerson = true;
            		//addActionMessage(request, "error.addPerson", "Cannot submit the registration!");
            		//forward = mapping.findForward(UIConstants.FAILURE);
             	}
        	} else {
        		// no in-process registration, consider status of: completed, or canceled, or no records at all
        		List appStatusList = this.getApplicationInProcessService().getApplicationStatusesByIcn(shortVpid);
				boolean isRegistrationCompleted =
					this.getApplicationInProcessService().existsRecordWithStatus(appStatusList, this.getLookupService().getApplicationStatusByCode(ApplicationStatus.COMPLETE.getCode()));

				/* In IDM, in ADR person_Table, no records in in-progress table OR records found with the status Completed
				you have a person object from the ADR person table
				            You will check the enrollment table existence.
				            If found, you will take them to overview screens.
				            If no rows found in enrollment table, you will take them to overview screens(locked)
				*/
			       /*CR14048AAP-No Enrollment Determination-*/
/*			        if (appStatusList == null || appStatusList.isEmpty() || isRegistrationCompleted) { */
					if (isRegistrationCompleted) {
					sessionPerson = esrPerson;
					shouldDisableAddPerson = true;
				} else {
					/*
					 * otherwise it's cancelled:

					In IDM, in ADR person_Table, In in-progress table with the status (cancelled) -
					you have a person object from the ADR person table . You will check the enrollment table existence.
					            If found, you will take them to overview screens.
					            If no rows found in enrollment table:
					We have a person object from IDM search results
					Create a stub record in Enrollment _application table
					allow the user to create a new registration and continue.
					*/

					if (enrollDet != null) {
						// enrollment already exists, a regular person
						sessionPerson = esrPerson;
						shouldDisableAddPerson = true;
					} else {
						// allow registration to be re-started

						// Set the personId into the person object so that it can be saved to the in-process table
						sessionPerson = idmSearchResultPerson;
						sessionPerson.setIdentifier(esrPerson.getEntityKey().getKeyValue());

						// Create a stub/update record in Enrollment _application table
				        getApplicationInProcessService().savePersonInProcess(sessionPerson,
				        		this.getLookupService().getApplicationStatusByCode(
								ApplicationStatus.NEW_APPLICATION.getCode()));
				        /*CR14048AAP-No Enrollment Determination*/
				        sessionPerson.setPersonLockedReason(null);
    				    putSandboxEntry(request, ApplicationConstants.SessionData.ADD_A_PERSON, new Boolean(true));
					}
				}
        	}
        }
    	else {
    		/* In IDM, not in ADR person table
    		We have a person object from IDM search results
    		Check and request for ESR 200 correlation
    		Create a stub record in Person_Table by ourselves
    		Create a stub record in Enrollment _application table
    		Allow the user continue with the registration
    		*/

    		sessionPerson = idmSearchResultPerson;
    		getApplicationInProcessService().processAddPersonStubAndSaveInProcess(sessionPerson);

	        /*CR14048AAP-No Enrollment Determination*/
	        sessionPerson.setPersonLockedReason(null);
            putSandboxEntry(request, ApplicationConstants.SessionData.ADD_A_PERSON, new Boolean(true));
       	}

		// Save the proper person object to session
	    savePersonToSession(sessionPerson, request);
		if (shouldDisableAddPerson) {
			// Not the case of add a person, turn off AddAPerson session flag
	        putSandboxEntry(request, ApplicationConstants.SessionData.ADD_A_PERSON, new Boolean(false));
		}
		return forward;
    }

    /**
     * Retrieve the person from the database and store in the session.
     *
     * @param personIdString The person Id (as a string) to retrieve
     * @param request A http request from an search.jsp page
     */
    public void retrievePerson(String personIdString, HttpServletRequest request) throws Exception
    {
    	retrievePerson(personIdString, request, null);
    }

    /**
     * Retrieve the person from the database and store in the session.
     *
     * @param personIdString The person Id (as a string) to retrieve
     * @param request A http request from an search.jsp page
     * @param traits Any previously cached traits, to help minimize number of Idm 1305 search calls (CCR11593)
     */
    private void retrievePerson(String personIdString, HttpServletRequest request, PersonIdentityTraits traits) throws Exception
    {
        Person person = null;
        if (SearchAction.isMockPersonRetrieveEnabled())
        {
            // Get the mock person (or retrieve the person with the specified person Id)
            person = getMockupPerson(personIdString);
        }
        else
        {
            // Retrieve the person from the database
            PersonEntityKey entityKey = CommonEntityKeyFactory.createPersonIdEntityKey(personIdString);
            person = getPersonService().getPerson(entityKey, traits);

            //get open cases count for veteran
            person.setOpenCasesCount(getWorkflowService().getOpenCasesCount(
                    person.getPersonEntityKey()));

        }

        savePersonToSession(person, request);
     }

    private void savePersonToSession(Person person, HttpServletRequest request) {
        // Clear out various items from session that were associated with the previously selected veteran.
        SessionManager.removeVeteranHeaderBean(request);
        SessionManager.removeMessageList(request);
        SessionManager.removeSelectedFinancialIncomeYear(request);
        SessionManager.removeQRYZ07FacilityList(request);

        // Set the newly retrieved person and person Id in session
        setSelectedPerson(request, person);
    }

	 /**
	  * For Add a Person, gets an ESR Person based on the short vpidValue

	  * @param vpid
	  * @return
	  * @throws ServiceException
	  */
    private Person getESRPersonByVPID(String vpid) throws ServiceException {
    	Person person = null;
    	PersonEntityKey entityKey = null;

      	// for add a person, the MVI search only returns vpid value, no person id.  Therefore get personId before continuing
     	VPIDEntityKey vpidEntity = CommonEntityKeyFactory.createVPIDEntityKey(vpid);
    	entityKey = getPersonService().getPersonIdByVPID(vpidEntity);

    	if (entityKey != null) {
        	// Retrieve the person from the database using personId
        	person = getPersonService().getPerson(entityKey);
            //get open cases count for veteran
            person.setOpenCasesCount(getWorkflowService().getOpenCasesCount(
                    person.getPersonEntityKey()));
    	}

    	return person;
    }

    /**
     * Create a new person from the form search results
     * @param request
     * @param vpid  The short vpid returned from idm search result
     * @return
     */
    private Person createPersonFromSearchResult(HttpServletRequest request, String vpid) throws ServiceException {

    	String tableId = "personSearchTableId";
		List resultVetList = SearchValueListAdapter.getResultsFromSession(request.getSession(), tableId + SearchValueListAdapter.RESULTS_KEY);

		VeteranSearchBean vetBean = null;

		for (Iterator iter = resultVetList.iterator(); iter.hasNext();) {
			vetBean = (VeteranSearchBean) iter.next();

			if ((vetBean.getVpid() != null)) {
			String shortVpid = new String(vetBean.getVpid());
			shortVpid = shortVpid.substring(6,23);

			    if (shortVpid.equals(vpid)) {
				    try {
					    IdmServiceVO idmServiceVo = createIdmServiceVO(vetBean);
					    VPIDEntityKey vpidEntity = CommonEntityKeyFactory.createVPIDEntityKey(VPIDEntityKeyImpl.getLongVPID(vpid));



					    return convertIdmServiceVOToPerson(idmServiceVo, vpidEntity);
				    } catch (Exception e) {
					    throw new ServiceException("Unable to convert VeteranSearchBean to Person: " + vetBean + ", shortVpid = " + vpid);
				    }
			    }
		    }
		}
		// no match found, throw exception
		throw new ServiceException("Add a Person Select Person: No row in search result matches vpid: " + vpid + ". resultVetList = " + resultVetList);
    }

    // clears the search criteria in the session resets the form data
    public ActionForward clear(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        SearchActionForm searchForm = (SearchActionForm)form;
        searchForm.clear();
        if (SessionManager.isAddAPerson(request)) {

        	searchForm.setAddButtonDisabled(true);
        }


        return (SessionManager.isAddAPerson(request)) ?
        		mapping.findForward(FORWARD_DISPLAY_NEW) : mapping.findForward(UIConstants.FAILURE);
    }

    /**
     * Retrive the search criteria from the session and reexecute the query
     *
     * @param mapping
     * @param form
     * @param request
     * @param response
     *
     * @return
     * @throws Exception
     */
    public ActionForward research(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        return search(mapping, form, request, response);
    }

    /**
     * Resend the cached search results
     *
     * @param mapping
     * @param form
     * @param request
     * @param response
     *
     * @return
     * @throws Exception
     */
    public ActionForward refresh(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        return search(mapping, form, request, response);
    }

    // CCR 10471 - Add A Person
    public ActionForward addNewPerson(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        boolean isAddAPerson = SessionManager.isAddAPerson(request);

    	if (!isAddAPerson) {
			addActionMessage(request, "error.addPerson", "Please use Search and Add New Person Screen.");
        	return mapping.findForward("overview");
    	}

    	Person incoming = (Person) getSelectedPerson(request);
        if(incoming == null){
        	addActionMessage(request, new ActionMessage("error.noPersonFound"));
        	return mapping.findForward("overview");
        }
        if(!ValidateFormForMinField(request,incoming)){
        	return mapping.findForward("overview");
        }

        Person incomingPersonClone = (Person)incoming.clone();

        Person onFile = getApplicationInProcessService().processCompleteRegistration(incomingPersonClone);
        /* CR13612 � CompletRegistration �begin*/
  		if (onFile == null) {
			addActionMessage(request, "error.resubmitCompleteRegistration");
			return mapping.findForward("overview");
		}
		/* CR13612 � CompletRegistration �end*/
        try {
            // CCR11451 -- pass a clone of the incoming person to business layer
        	// so that the incoming person is a detached copy, this avoids hibernate
        	// dealing with two objects attached to the session

            if(isValidQueryInfo(incomingPersonClone)){
            	MessagingService messagingService = getMessagingService();
                messagingService.processTriggerBroker(incomingPersonClone) ;
            }
            else{
            	logger.error("Query Info is not valid for processTriggerBroker for Person with VPID:" + incoming.getVPIDValue());
             }

			addInformationMessage(request, "message.personAdded");

			// overlay identity traits from incoming to onFile as processing rules does not merge traits data for UI
			onFile.setIdentityTraits(incoming.getIdentityTraits());
			setSelectedPerson(request, onFile);

			putSandboxEntry(request, ApplicationConstants.SessionData.ADD_A_PERSON, new Boolean(false));
			return mapping.findForward("overview");
        }
		catch (ValidationServiceException ex){

			ValidationMessages mesg=	ex.getValidationMessages();
			Iterator  mesgItr=mesg.get();
			while(mesgItr.hasNext()){
				ValidationMessage msgObj= (ValidationMessage)mesgItr.next();
				addActionMessage(request, new ActionMessage(msgObj.getKey()));
    		}
		}

      	return mapping.findForward("overview");

    }

    public boolean  ValidateFormForMinField(HttpServletRequest request,Person person){
    	boolean valid=true;

    	/*
    	 *
    	 Map tabMap=new HashMap();
    	tabMap.put("demographicIdentityTraits", "fName");
    	tabMap.put("demographicIdentityTraits", "lName");
    	tabMap.put("demographicIdentityTraits", "DOB");
    	tabMap.put("demographicIdentityTraits", "SSN");
    	tabMap.put("demographicIdentityTraits", "gender");
    	tabMap.put("demographicIdentityTraits", "placeOfBirth");
    	tabMap.put("demographicIdentityTraits", "stateOfBirth");

    	*/
    	if(person.getNames() ==null){
    		 addActionMessage(request, 	"error.firstNameRequired");
    		 valid=false;

    	}
    	if(person.getBirthRecord()==null || person.getBirthRecord().getBirthDate()==null){
    		 addActionMessage(request, 	"error.dateOfBirthRequired");
    		 valid=false;
    	}
    	if(person.getBirthRecord()==null || StringUtils.isBlank(person.getBirthRecord().getCity())){
    		 addActionMessage(request, 	"error.placeOfBirthRequired");
    		 valid=false;
    	}
    	if(person.getBirthRecord()==null ||	StringUtils.isBlank(person.getBirthRecord().getState())) {
    		 addActionMessage(request, 	"error.stateOfBirthRequired");
    		 valid=false;
    	}
    	if(person.getGender()==null) {
    		 addActionMessage(request, 	"error.birthSexRequired");
    		 valid=false;
    	}
    	if(person.getIdentityTraits().getSsnText()==null) {

    		 addActionMessage(request, 	"error.ssnRequired");
    		 valid=false;
    	} else
    	{
    		if (!isValidSSN(request, person))
    			valid = false;
    	}


    	if(person.getPreferredFacilities().isEmpty()) {

      		 addActionMessage(request, 	"error.preferredFacilityRequired");
      		 valid=false;
      	}
    	if(person.getMaritalStatus() ==null ) {

     		 addActionMessage(request, 	"error.maritalStatusRequired");
     		 valid=false;
     	}
    	if(person.getAddresses() ==null ||person.getAddresses().size()<1) {

   		 addActionMessage(request, 	"error.addressRequired");
   		 valid=false;
     	}
    	//CCR11451 AAP:  Remove the reqt that says MS data is required when adding a person
    	/*if(person.getMilitaryService() ==null ||person.getMilitaryService().getMilitaryServiceSiteRecords()==null ||
    			person.getMilitaryService().getMilitaryServiceSiteRecords().size()<1) {

      		 addActionMessage(request, 	"error.militaryServiceRequired");
      		 valid=false;
        	} */
    	if(person.getPermanentAddress() == null){
    		addActionMessage(request, 	"error.addressRequired");
     		 valid=false;
    	}
    	if(person.getApplication() == null || person.getApplication().getApplicationDate() == null){
    		addActionMessage(request, 	"error.applicationDateRequired");
    		 valid=false;

    	}
    	if(person.getVeteran() == null){
    		addActionMessage(request, 	"error.veteranIndicatorRequired");
   		 	valid=false;

    	}
    	if(person.getEligibilityVerification() == null ||person.getEligibilityVerification().getEligibilityStatus() == null){
    		addActionMessage(request, 	"error.eligibilityStatusRequired");
   		 	valid=false;

    	}



    	return valid;
    }


    private boolean isValidSSN(HttpServletRequest request, Person person)
    {
    	boolean valid = true;

		/*
		Invalid Values
		The first five digits of an SSN may not be zeros (00000).  The record for which this is true will not be accepted; however, an application error (AE) should not be generated.
		If any of the following conditions is found to be true for an SSN, the system will compute a pseudo SSN:
		1.	All digits of the SSN are the same number (e.g., 111111111, 222222222, 333333333, etc.)
		2.	The first three digits of the SSN are 000
		3.	The fourth and fifth digits of the SSN are 00
		4.	The last four digits of the SSN are 0000
		5.	The digits of the SSN are 123456789

	 */
		//CCR Validate SSN
		String ssn = person.getIdentityTraits().getSsnText().replaceAll("-", "");

		if (	ssn.startsWith("00000") || //leading 5 0s
				ssn.startsWith("000") || //2 - leading 3 0s
				ssn.endsWith("0000") || //4 - ending 4 0s
				ssn.substring(3, 5).equals("00") || //3 - 4th, 5th )s
				ssn.equals("111111111") || //1 - same digits
				ssn.equals("222222222") ||
				ssn.equals("333333333") ||
				ssn.equals("444444444") ||
				ssn.equals("555555555") ||
				ssn.equals("666666666") ||
				ssn.equals("777777777") ||
				ssn.equals("888888888") ||
				ssn.equals("999999999") ||
				ssn.equals("123456789") ) //5
		{
			addActionMessage(request, 	"error.ssnInvalid");
   		 	valid=false;
		}

		return valid;

    }
    private void setMultipleBirth(Person person, String setYes)
    {
        BirthRecord birthRecord = person.getBirthRecord();

        if (setYes == null || setYes.equalsIgnoreCase(ConvertUtils.NULL_VALUE))
        {
            if (birthRecord != null) {
                birthRecord.setMultipleBirth(null);
            }
        }
        else
        {
            if (birthRecord == null)
                birthRecord = new BirthRecord();

            birthRecord.setMultipleBirth(ConvertUtils.convertBoolean(setYes));
            person.setBirthRecord(birthRecord);
        }
    }


    /**
     * helper method. Convert ActionForm to IdmServiceVO
     */
	private IdmServiceVO createIdmServiceVO(SearchActionForm form) throws Exception  {

		IdmServiceVO idmServiceVO = new IdmServiceVO();
		//traits.setNames(person.getNames());

		Name lName = new Name();
		String prefixName = "";
		lName.setGivenName(form.getGivenName() != null ? form.getGivenName() : "");
		lName.setMiddleName(form.getMiddleName() != null ? form.getMiddleName() : "");
		lName.setFamilyName(form.getFamilyName() != null ? form.getFamilyName() : "");
		lName.setType(getLookupService().getNameTypeByCode(NameType.LEGAL_NAME.getName()));

		HashSet names = new HashSet();
		names.add(lName);
		idmServiceVO.setNames(names);

		BirthRecord br = new BirthRecord();
		br.setBirthDate(new ImpreciseDate(form.getDateOfBirth()));

		idmServiceVO.setBirthRecord(br);
		Gender gender = getLookupService().getGenderByCode(form.getGender());
		idmServiceVO.setGender(gender);
		//idmServiceVO.setSigi(form.getSelfIdentifiedGenderIdentity());

		Address permAddress = new Address();
		permAddress.setLine1(form.getAddressLine1());
		permAddress.setLine2("");
		permAddress.setLine3("");
		permAddress.setCity(form.getCity() != null ? form.getCity() : "");
		permAddress.setState(form.getState() != null ? form.getState() : "");
		permAddress.setZipCode(form.getZipCode() != null ? form.getZipCode() : "");
		permAddress.setPostalCode(form.getPostalCode() != null ? form.getPostalCode() : "");

		//Default country to USA if country is not selected as part of Add person through AAP screen - ESR_CodeCR13036
		String country = form.getCountry() != null ? form.getCountry() : "";
		if (StringUtils.isEmpty(country)) {
			country = USA;
		}
		permAddress.setCountry(country);
		permAddress.setPhoneNumber(form.getHomePhoneNumber() != null ? form.getHomePhoneNumber() : "");
		permAddress.setType(getLookupService().getAddressTypeByCode("P"));
		idmServiceVO.addAddress(permAddress);

		SSN ssN = new SSN();
		ssN.setSsnText(form.getSsn());
		idmServiceVO.setSsn(ssN);

		return idmServiceVO;
	}

	/**
    * helper method. Convert VeteranSearchBean to IdmServiceVO
    */
	private IdmServiceVO createIdmServiceVO(VeteranSearchBean bean) throws Exception  {

		IdmServiceVO idmServiceVO = new IdmServiceVO();

		Name lName = new Name();
		lName.setGivenName(bean.getFirstName() != null ? bean.getFirstName() : "");
		lName.setMiddleName(bean.getMiddleName() != null ? bean.getMiddleName() : "");
		lName.setFamilyName(bean.getLastName() != null ? bean.getLastName() : "");
		lName.setType(getLookupService().getNameTypeByCode(NameType.LEGAL_NAME.getName()));

		HashSet names = new HashSet();
		names.add(lName);
		idmServiceVO.setNames(names);

		BirthRecord br = new BirthRecord();
		br.setBirthDate(new ImpreciseDate(bean.getDateOfBirth()));
		idmServiceVO.setBirthRecord(br);
		idmServiceVO.setGender(bean.getGender());
		//idmServiceVO.setSigi(bean.getSigi());

		Address permAddress = new Address();
		permAddress.setLine1(bean.getAddress());
		permAddress.setLine2("");
		permAddress.setLine3("");
		permAddress.setCity(bean.getCity() != null ? bean.getCity() : "");
		permAddress.setState(bean.getState() != null ? bean.getState() : "");
		permAddress.setZipCode(bean.getZipCode() != null ? bean.getZipCode() : "");
		permAddress.setPostalCode(bean.getPostalCode() != null ? bean.getPostalCode() : "");

		//Default country to USA if country is not selected as part of Add person through AAP screen - ESR_CodeCR13036
		String country = bean.getCountry() != null ? bean.getCountry() : "";
		if (StringUtils.isEmpty(country)) {
			country = USA;
		}
		permAddress.setCountry(country);
		permAddress.setPhoneNumber(bean.getHomePhoneNumber() != null ? bean.getHomePhoneNumber() : "");
		permAddress.setType(getLookupService().getAddressTypeByCode("P"));
		idmServiceVO.addAddress(permAddress);

		SSN ssN = new SSN();
		ssN.setSsnText(bean.getSsn());
		idmServiceVO.setSsn(ssN);

		return idmServiceVO;
	}


	/*
	 * Helper method
	 * Convert the IdmServiceVO to Person object
	 */
    private Person convertIdmServiceVOToPerson(IdmServiceVO idmServiceVO, VPIDEntityKey vpid)
    	throws ServiceException
	{
    	if (vpid == null)
	        return null;

    	Person target = new Person(vpid);

	    // name
	    target.addName(idmServiceVO.getLegalName());

	    // dob
	    BirthRecord dob = idmServiceVO.getBirthRecord();

	    //** if dob is not available or contains only the year, set to a default
	    //** (Corrects error that occurs when processing Imprecise Date for dob on inbound record)
	    ImpreciseDate defaultDob;
	    if (dob != null && dob.getBirthDate() != null && dob.getBirthDate().getString() != null && (dob.getBirthDate().getString().length() == 4
	    		|| dob.getBirthDate().getString().length() == 6)) {

	    	if(dob != null && dob.getBirthDate() != null && dob.getBirthDate().getString() != null && dob.getBirthDate().getString().length() == 4){
	    		defaultDob = new ImpreciseDate("01/01/" + dob.getBirthDate().getString());
	    	}
	    	else if(dob != null && dob.getBirthDate() != null && dob.getBirthDate().getString() != null && dob.getBirthDate().getString().length() == 6){
	    		String month = "";
	    		String year = "";

	    		year = dob.getBirthDate().getString().substring(0, 4);
	    		month = dob.getBirthDate().getString().substring(4, 6);

	    		defaultDob = new ImpreciseDate(month + "/01/" + year);
	    	}
	    	else{
	    		defaultDob = new ImpreciseDate("01/01/1900");
	    	}

	    	dob.setBirthDate(defaultDob);
	    }

        target.setBirthRecord(dob);

	    // Gender
	    target.setGender(idmServiceVO.getGender());
	    //target.setSelfIdentifiedGenderIdentity(idmServiceVO.getSigi());

	    // SSNS
	    SSN ssn = idmServiceVO.getSsn();
	    ssn.setType(getLookupService().getSSNTypeByCode(SSNType.CODE_ACTIVE.getName()));
	    target.addSsn(idmServiceVO.getSsn());

	    // IdM match type:
	    target.setIdmMatchType(idmServiceVO.getIdmMatchType());

	    // set a default application method
        Application application = new Application();
        application.setPerson(target);

        application.setAppliactionMethod(this.getLookupService().getApplicationMethodByCode(
    					ApplicationMethod.IN_PERSON.getCode()));
        target.setApplication(application);

        return target;
	}

    // Lookup dispatch action methods
    protected Map getKeyMethodMap()
    {
        Map map = new HashMap();
        map.put("button.display", "display");

        //CodeCR10471_WS_Add a Person Record capability to ESR
        map.put("button.displayNew", "displayNew");
        map.put("button.displayStatusHistory", "displayStatusHistory");
        map.put("button.completeRegistration", "addNewPerson");
        map.put("button.saveInProcess", "saveInProcess");
        map.put("button.cancelRegistration", "cancelRegistration");
        map.put("button.searchAddAPerson", "searchAddAPerson");
        map.put("button.add", "addNewPersonScreen");

        map.put("button.search", "search");
        map.put("button.research", "research");
        map.put("button.clear", "clear");
        map.put("button.refresh", "refresh");
        map.put("button.cancel", "clear");
        map.put("button.selectPerson", "selectPerson");
        return map;
    }

    /**
     * Override default implementation to always returns false.
     * @return false
     */
    protected boolean requiresSelectedPerson()
    {
        return false;
    }

    /**
     * Returns whether a mock person retrieval should be used.
     *
     * @return True if mock retrieval should be used or false if not.
     */
    public static boolean isMockPersonRetrieveEnabled()
    {
        return System.getProperty(USE_MOCK_DEBUG_FLAG) == null ? false : true;
    }

    /**
     * Returns whether mock person creation should be used.
     *
     * @return True if mock creation should be used or false if not.
     */
    public static boolean isMockPersonCreateEnabled()
    {
        return System.getProperty(CREATE_MOCK_DEBUG_FLAG) == null ? false : true;
    }

    public Person getMockupPerson(String personId) throws Exception
    {
        // Create a mock person if extra flag is set
        if (isMockPersonCreateEnabled())
        {
            getMockPersonBuilder().createPersonInDB();
        }

        // Retrieve the mock person
        return getMockPersonBuilder().getPerson(personId);
    }

    public MockPersonBuilder getMockPersonBuilder()
    {
        return mockPersonBuilder;
    }

    public void setMockPersonBuilder(MockPersonBuilder mockPersonBuilder)
    {
        this.mockPersonBuilder = mockPersonBuilder;
    }



    private void addDefaultValues(Person person, SearchActionForm form) {
    	 addAddressToPerson(person, form);
    	 setEligibility(person);
    	 setSSAStatus(person);
    }
    private String setAddressField(String fieldValue) {
    	if (fieldValue == null || fieldValue.length() == 0) {
    		return "";
    	}
    	return fieldValue;

    }
    // A counter for the number of address fields with a value.
	//int validFields = 0;


    /**
     * Copy the address from the form to the person.  Use the address from the form and ignore whatever
     * was returned by the IdmService.
     * @param person
     * @param form
     */
    private void addAddressToPerson(Person person, SearchActionForm form) {

    	Address address = new Address();

    	//Default country to USA if country is not selected as part of Add person through AAP screen - ESR_CodeCR13036
		String country = form.getCountry() != null ? form.getCountry() : "";
		if (StringUtils.isEmpty(country)) {
			country = USA;
		}
    	address.setCountry(setAddressField(country));

    	// Reset the validFields because there will always be a country.
     	int validFields = 0;
     	if (StringUtils.isNotEmpty(form.getAddressLine1())) {
     		validFields++;
     	}
    	address.setLine1(setAddressField(form.getAddressLine1()));

     	if (StringUtils.isNotEmpty(form.getCity())) {
     		validFields++;
     	}
    	address.setCity(setAddressField(form.getCity()));

     	if (StringUtils.isNotEmpty(form.getState())) {
     		validFields++;
     	}
    	address.setState(setAddressField(form.getState()));

     	if (StringUtils.isNotEmpty(form.getZipCode())) {
     		validFields++;
     	}
    	address.setZipCode(setAddressField(form.getZipCode()));

     	if (StringUtils.isNotEmpty(form.getZipPlus4())) {
     		validFields++;
     	}
    	address.setZipPlus4(setAddressField(form.getZipPlus4()));

     	if (StringUtils.isNotEmpty(form.getCounty())) {
     		validFields++;
     	}
    	address.setCounty(setAddressField(form.getCounty()));

     	if (StringUtils.isNotEmpty(form.getHomePhoneNumber())) {
     		validFields++;
     	}
    	address.setPhoneNumber(setAddressField(form.getHomePhoneNumber()));
    	try {
    		//Default country to USA if country is not selected as part of Add person through AAP screen - ESR_CodeCR13036
    		String countryCode = country;
    		if (StringUtils.isNotEmpty(countryCode)) {
	    		Country newCountry = (Country)getLookupService().getCountryByCode(countryCode);
	    		String countryShortName = newCountry.getShortName();
	    		Country countryObject = new Country();
	    		countryObject.setShortName(countryShortName);
	    		address.setCountryObject(countryObject);
    		}

			address.setType(this.getLookupService().getAddressTypeByCode(
						AddressType.CODE_PERMANENT_ADDRESS.getCode()));

	    	String homePhone = form.getHomePhoneNumber();
	    	if (StringUtils.isNotEmpty(homePhone)) {
	    		Phone phone = new Phone();
	    		phone.setType(this.getLookupService().getPhoneTypeByCode(PhoneType.CODE_HOME.getName()));
	    		phone.setPhoneNumber(homePhone);
	    		person.addPhone(phone);
	    	}
		} catch (Exception e) {
			// This should never happen
		}

    	// if any fields were set then add the address to the person
    	if (validFields > 0) {
    		person.addAddress(address);
    	}
    }

    private void setSSAStatus(Person person) {
    	//set default ssa status for new add
    	SSAVerificationStatus ssnNew = new SSAVerificationStatus();
    	try {
     		ssnNew = this.getLookupService().
    			getSSAVerificationStatusByCode(SSAVerificationStatus.NEW_RECORD.getCode());
     	} catch (Exception e){

     	}
     	person.getIdentityTraits().getSsn().setSsaVerificationStatus(ssnNew);
    }

    private void setEligibility(Person person) {
        // default the person to a veteran CCR 10889
        person.setVeteran(Boolean.TRUE);

    	EligibilityVerification ev = new EligibilityVerification();
    	try {
			ev.setEligibilityStatus(this.getLookupService().getEligibilityStatusByCode(
					EligibilityStatus.CODE_PENDING_VERIFICATION.getCode()));
		} catch (Exception e) {
			// do nothing. This should not happen
		}
    	person.setEligibilityVerification(ev);

    }

    private boolean isValidQueryInfo(Person person) {

		if (passedNullValidation(person)) {
			if (invalidQuery(person)) {
				return false;
			} else
				return true;

		} else
			return false;

	}

	private boolean invalidQuery(Person person){

		if (person.getIdentityTraits().getLegalName()
				.getGivenName()== null
				|| person.getIdentityTraits().getLegalName()
						.getGivenName().length() == 0
				|| person.getIdentityTraits().getLegalName()
						.getGivenName().trim().length() == 0

				|| person.getIdentityTraits().getSsnText()== null
				|| person.getIdentityTraits().getSsnText()
						.length() == 0
				|| person.getIdentityTraits().getSsnText()
						.trim().length() == 0

				|| person.getIdentityTraits()
						.getLegalName().getFamilyName()== null
				|| person.getIdentityTraits()
						.getLegalName().getFamilyName().length()== 0
				|| person.getIdentityTraits()
						.getLegalName().getFamilyName().trim().length()== 0

				|| person.getIdentityTraits().getGender()
						.getCode() == null
				|| person.getIdentityTraits().getGender()
						.getCode().length()== 0
				|| person.getIdentityTraits().getGender()
						.getCode().trim().length()== 0

				|| person.getIdentityTraits()
						.getBirthRecord().getBirthDate() == null){
			return true;

		}
		else
			return false;

	}

	public boolean passedNullValidation(Person person) {
		if (person.getIdentityTraits() != null
				&& person.getIdentityTraits().getLegalName() != null
				&& person.getGender() != null
				&& person.getBirthRecord() != null) {
			return true;

		} else
			return false;

	}
}