/********************************************************************
 * Copyright © 2004-2006 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.ui.demographic.action;

// Java Classes


import gov.va.med.esr.common.infra.ImpreciseDate;
// ESR Classes
import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.ee.Application;
import gov.va.med.esr.common.model.lookup.BenefitType;
import gov.va.med.esr.common.model.lookup.DeathDataSource;
import gov.va.med.esr.common.model.lookup.EmergencyResponse;
import gov.va.med.esr.common.model.lookup.EmploymentStatus;
import gov.va.med.esr.common.model.lookup.Language;
import gov.va.med.esr.common.model.lookup.MaritalStatus;
import gov.va.med.esr.common.model.lookup.NameType;
import gov.va.med.esr.common.model.lookup.Relationship;
import gov.va.med.esr.common.model.lookup.Religion;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.lookup.SensitivityChangeSource;
import gov.va.med.esr.common.model.lookup.SourceDesignation;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.person.DeathRecord;
import gov.va.med.esr.common.model.person.EmergencyResponseIndicator;
import gov.va.med.esr.common.model.person.Employment;
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.PreferredFacility;
import gov.va.med.esr.common.model.person.PreferredLanguage;
import gov.va.med.esr.common.model.person.Relation;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.common.util.CommonDateUtils;
import gov.va.med.esr.service.PreferredFacilityService;
import gov.va.med.esr.service.SystemParameterService;
import gov.va.med.esr.service.UnknownLookupTypeException;
import gov.va.med.esr.ui.common.action.AddressConversionService;
import gov.va.med.esr.ui.common.service.LookupCacheService;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.esr.ui.common.util.JspUtils;
import gov.va.med.esr.ui.util.ConvertUtils;
// Framework Classes
import gov.va.med.fw.conversion.ConversionServiceException;
import gov.va.med.fw.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

// Library Classes
import org.apache.commons.lang.Validate;

/**
 * Converts Personal Demographic information to the DemographicPersonalForm and vice versa.
 *
 * @author DNS   KATIKM
 * @author Andrew Pach
 */
// public class DemographicPersonalConversionService extends UIConversionServiceImpl
public class DemographicPersonalConversionService extends AddressConversionService {
    public static final String NAME_BREAK = " ";
    public static final String VERIFIED = "(VERIFIED)";
    public static final String UNVERIFIED = "(UNVERIFIED)";

    private PreferredFacilityService preferredFacilityService;

    /**
     * Get the preferredFacilityService.
     * @return the preferredFacilityService
     */
    public PreferredFacilityService getPreferredFacilityService() {
        return preferredFacilityService;
    }

    /**
     * Set the preferredFacilityService.
     * @param preferredFacilityService new PreferredFacilityService value to set
     */
    public void setPreferredFacilityService(PreferredFacilityService preferredFacilityService) {
        this.preferredFacilityService = preferredFacilityService;
    }

    /**
     * Converts between a Person object and the DemographicPersonalForm. It only converts Person to Form and not vice versa.
     *
     * @param source
     *            the source object
     * @param target
     *            the target object
     *
     * @throws gov.va.med.fw.conversion.ConversionServiceException
     *             if any errors were encountered during the conversion.
     */
    protected void convertBean(Object source, Object target) throws ConversionServiceException {
        Validate.notNull(source, "DemographicPersonalConversionService source is null");
        Validate.notNull(target, "DemographicPersonalConversionService target is null");

        if ((source instanceof Person) && (target instanceof DemographicPersonalForm)) {
            convertPersontoForm((Person) source, (DemographicPersonalForm) target);
        } else {
            if ((target instanceof Person) && (source instanceof DemographicPersonalForm)) {
                convertFormToPerson((DemographicPersonalForm) source, (Person) target);
            } else {
                throw new ConversionServiceException("Type mismatch: Can't convert from " + source.getClass().getName()
                        + " to " + target.getClass().getName());
            }
        }
    }

    /**
     * Populate data from the Person object onto the form.
     *
     * @param person
     *            The person
     * @param form
     *            The form
     *
     * @throws ConversionServiceException
     *             if any conversion problems were encountered
     */
    private void convertPersontoForm(Person person, DemographicPersonalForm form) throws ConversionServiceException {
        try {
            boolean isAddAPerson = form.isAddAPerson();
            Boolean sensitiveRecord = person.getSensitiveRecord();
            form.setSensitivityFlag(sensitiveRecord != null && sensitiveRecord.booleanValue());
            if (person.getSensitivityChangeSource() != null) {
                form.setSensitivityFlagSourceOfUpdate(person.getSensitivityChangeSource().getCode());
            }
            if (person.getSensitivityChangeSite() != null) {
                form.setSensitivityFlagSiteOfUpdate(person.getSensitivityChangeSite().getCode());
            }

            // Default the Source of Change to HEC (per 2763[UC14.22]).
            form.setSensitivityFlagSourceOfUpdate(SensitivityChangeSource.CODE_HEC.getName());

            // Default the Site of Change to HEC (per 4117[UC14.30.1])
            form.setSensitivityFlagSiteOfUpdate(VAFacility.CODE_HEC.getName());

            // Set other Names
            Set otherNames = new HashSet(person.getNames());
            Name name = person.getLegalName();
            if (name != null) {
                // Remove the legal name from all names to get the other names
                otherNames.remove(name);
            }
            form.setOtherNames(JspUtils.displayValues(otherNames, "", null));

            SystemParameterService systemParameterService = (SystemParameterService) this.getComponent("systemParameterService");

            DeathRecord deathRecord = person.getDeathRecord();
            if (deathRecord != null){
            	if (deathRecord.getDeathDate() != null) {
            		form.setDateOfDeath(DateUtils.formatForEdit(deathRecord
            				.getDeathDate(), null));
            		/*
            		if (deathRecord.getDodVerifiedInd() == null
            				|| deathRecord.getDodVerifiedInd()) {
            			form.setDeathVerifyStatus(VERIFIED);
            		} else {
            			form.setDeathVerifyStatus(UNVERIFIED);
            		}
            		*/
            		form.setDeathNotificationSource(getLookupCode(deathRecord.getDataSource()));
            		form.setDeathNotificationSite(getLookupCode(deathRecord.getFacilityReceived()));
            		form.setDeathNotificationSourceDesc(deathRecord.getDataSource()!= null ? deathRecord.getDataSource().getDescription(): null);
            		form.setDeathNotificationSiteName(deathRecord.getFacilityReceived() != null? deathRecord.getFacilityReceived().getSiteNumberAndName(): null);
            		form.setDateOfDeathReport(DateUtils.formatWithTime(deathRecord.getDeathReportDate(), null));



            		//if system parameter is Y let ES user allow es user to modify date of death only if it was entered by a es user
            		if (systemParameterService.getDODIndicator())
            		{

            		  if ((deathRecord.getDeathReportedBy() != null)
            				&& (deathRecord.getDeathReportedBy().equalsIgnoreCase("ES_USER"))) {
            			form.setDodEditableFlag(true);
               		  }
            	    }
            		//if system parameter is not Y let all users modify date of death and show all death notification sources
            		else {
                 		form.setDodEditableFlag(true);
             			form.setShowAllDeathSourcesFlag(true);
                 	}
            	} else {
            		form.setDodEditableFlag(true);
            	}
            } else {
            	if (!systemParameterService.getDODIndicator())
            	{
            	 	form.setShowAllDeathSourcesFlag(true);
            	}

            	form.setDodEditableFlag(true);
            }


            form.setDegree(person.getDegree());

            // CCR10640 -- preferred facility changes
            List preferredFacilities = getPreferredFacilityService().getDisplayPreferredFacilities(person);
            addPreferredFacilitiesToForm(preferredFacilities, form);

            if (person.getClaimFolderNumber() != null) {
                form.setClaimFolderNumber(person.getClaimFolderNumber());
            }

            // Defect 2051 display claim folder location even the claim folder number is null
            form.setClaimFolderLocation(getLookupCode(person.getClaimFolderLocation()));

            convertPersontoFormPreferredLanguage(person, form);

            // Populate Emergency responses.
            this.populateEmergencyReponseToForm(person, form);

            // TODO field type mistamtch (date and integer(imprecise date contains only year)
            if (person.getUserEnrolleeValidThrough() != null) {
                form.setUserEnrolleeValidthroughDate(person.getUserEnrolleeValidThrough().toString());
            }

            form.setUserEnrolleeSite(getLookupCode(person.getUserEnrolleeSite()));

            form.setAppointmentRequestDate(DateUtils.format(person.getAppointmentRequestDate(), null));
            Boolean response = person.getAppointmentRequestResponse();
            if (response == null)
                form.setAppointmentRequestResponse(null);
            else {
                form.setAppointmentRequestResponse(response.booleanValue() ? "Yes" : "No");
            }

         // CCR-13236 if person.getOfficialSsn().getSsnText() an exception will occur. Add logic to prevent this.
            form.setSsn((person.getOfficialSsn() == null || person.getOfficialSsn().getSsnText() == null) ? null :
                person.getOfficialSsn().getSsnText().replaceAll("-", ""));


            Set otherSsns = new HashSet(person.getOtherSsns());
            form.setOtherSsns(JspUtils.displayValues(otherSsns, "", null));

            // Update the Sensitivity Source of Change to HEC if one isn't set currently
            if (form.getSensitivityFlagSourceOfUpdate() == null) {
                form.setSensitivityFlagSourceOfUpdate(SensitivityChangeSource.CODE_HEC.getName());
            }

            form.setMaritalStatus(getLookupCode(person.getMaritalStatus()));
            form.setReligion(getReligion(person));
            form.setBenefitAppliedFor(getBenefitAppliedFor(person));

            if (isAddAPerson) {
                form.setNeedCareDueToAccident(ConvertUtils.convertYesNoNoData(person.getNeedCareDueToAccident()));
                form.setNeedCareDueToInjury(ConvertUtils.convertYesNoNoData(person.getNeedCareDueToInjury()));
                form.setOtherFirstNames(this.displayValues(getOtherFirstNames(person), "", null));
                form.setOtherLastNames(this.displayValues(getOtherLastNames(person), "", null));
                if (person.getFather() != null) {
                    form.setFathersFirstName((JspUtils.displayValue(person.getFather().getName() != null ? person.getFather()
                            .getName().getGivenName() : null, "")));
                    form.setFathersLastName((JspUtils.displayValue(person.getFather().getName() != null ? person.getFather()
                            .getName().getFamilyName() : null, "")));
                } else {
                    form.setFathersFirstName(JspUtils.displayValue(null, ""));
                    form.setFathersLastName(JspUtils.displayValue(null, ""));
                }
                if (person.getMother() != null) {
                    form.setMothersFirstName((JspUtils.displayValue(person.getMother().getName() != null ? person.getMother()
                            .getName().getGivenName() : null, "")));
                    form.setMothersLastName((JspUtils.displayValue(person.getMother().getName() != null ? person.getMother()
                            .getName().getFamilyName() : null, "")));
                } else {
                    form.setMothersFirstName(JspUtils.displayValue(null, ""));
                    form.setMothersLastName(JspUtils.displayValue(null, ""));
                }
            } else {
                form.setFathersName((JspUtils.displayValue(person.getFather() != null ? person.getFather().getName() : null, "")));
                form.setMothersName((JspUtils.displayValue(person.getMother() != null ? person.getMother().getName() : null, "")));
            }

            Employment employment = person.getEmployment();
            if (employment != null) {
                form.setEmploymentStatus(getLookupCode(employment.getEmploymentStatus()));
                form.setOnFileEmploymentStatus(getLookupCode(employment.getEmploymentStatus()));
                form.setEmployerName(employment.getEmployerName());
                form.setOccupation(employment.getOccupation());
                if (isAddAPerson) {
                    Address address = employment.getEmployerAddress();
                    // Convert the standard address fields
                    convertAddressToForm(address, form);
                } else {
                    form.setEmployerAddress(JspUtils.displayAddress(employment.getEmployerAddress()));
                }
                form.setEmployerPhone(employment.getEmployerPhone());
                if (employment.getRetirementDate() != null) {
                    form.setRetirementDate(DateUtils.formatForEdit(employment.getRetirementDate(), null));
                }
            }
        } catch (Exception ex) {
            throw new ConversionServiceException("Conversion Failed", ex);
        }
    }

    /**
     * Converts the Preferred Language portion of Person to the Form.
     * If the person does not contain a preferred language, the form will be defaulted to 'eng' for English.
     * If the person does not contain a language entry date, the form will be defaulted to the current date (no time).
     * Note that setting these defaults on the form do not guarantee the user will submit the form back to be persisted on the person.
     * @param person the source person
     * @param form the target form
     */
    private void convertPersontoFormPreferredLanguage(Person person, DemographicPersonalForm form) {

        if (person != null && person.getPreferredLanguage() != null) {
            if(person.getPreferredLanguage().getLanguageEntryDate() != null){
                form.setLanguageEntryDate(DateUtils.format(person.getPreferredLanguage().getLanguageEntryDate(), DateUtils.MMDDYYYY));
            }
        }

        if (person != null && person.getPreferredLanguage() != null && person.getPreferredLanguage().getLanguage() != null
                    && person.getPreferredLanguage().getLanguage().getCode() != null) {
                form.setPreferredLanguageCode(person.getPreferredLanguage().getLanguage().getCode());
        }

        if (StringUtils.isEmpty(form.getPreferredLanguageCode())){

            //code is empty, default it to English per requirements.  However, there is no guarantee that the user will save.
            form.setPreferredLanguageCode(Language.DEFAULT_LANGUAGE_CODE);
            log.info("Defaulted Preferred Language to " + form.getPreferredLanguageCode());
        }
    }

    /**
     * Populate data from the form to the Person object.
     *
     * @param form
     *            The source form
     * @param person
     *            The target person
     *
     * @throws ConversionServiceException
     *             if any conversion problems were encountered
     */
    private void convertFormToPerson(DemographicPersonalForm form, Person person) throws ConversionServiceException {
        LookupCacheService lookupCacheService = getLookupCacheService();
        try {
            // The sensitivity flag
            person.setSensitiveRecord(new Boolean(form.isSensitivityFlag()));

            // The sensitivity change source & site
            if (StringUtils.isEmpty(form.getSensitivityFlagSourceOfUpdate())) {
                // If no change source was entered, default to HEC
                form.setSensitivityFlagSourceOfUpdate(SensitivityChangeSource.CODE_HEC.getName());
            }
            if (StringUtils.isEmpty(form.getSensitivityFlagSiteOfUpdate())) {
                // If no change site was entered, default to HEC
                form.setSensitivityFlagSiteOfUpdate(VAFacility.CODE_HEC.getName());
            }
            person.setSensitivityChangeSource((SensitivityChangeSource) lookupCacheService.getByCodeFromCache(
                    SensitivityChangeSource.class, form.getSensitivityFlagSourceOfUpdate()));
            person.setSensitivityChangeSite((VAFacility) lookupCacheService.getByCodeFromCache(VAFacility.class,
                    form.getSensitivityFlagSiteOfUpdate()));

            person.setDegree(StringUtils.isBlank(form.getDegree()) ? null : form.getDegree());

            DeathRecord deathRecord = person.getDeathRecord();
            if (StringUtils.isNotEmpty(form.getDateOfDeath())) {
                if (deathRecord == null) {
                    // No previous record exists - create new one
                    deathRecord = new DeathRecord();
                    person.setDeathRecord(deathRecord);
                }

                // DOD
                // Time portion can be displayed (if it came from messaging), but can not be saved by the user.
                // So create an imprecise date with the time omitted.
                ImpreciseDate dateWithTime = DateUtils.getImpreciseDate(form.getDateOfDeath(), true);
                // If the user changed the death date/time only then update the death date
                if (deathRecord.getDeathDate() == null || !dateWithTime.equals(deathRecord.getDeathDate())) {
                    String impreciseString = dateWithTime.toStandardFormat();
                    if (impreciseString.length() > 8) {
                        impreciseString = impreciseString.substring(0, 8);
                    }
                    ImpreciseDate dateWithoutTime = new ImpreciseDate(impreciseString);
                    deathRecord.setDeathDate(dateWithoutTime);
                }

                // Death Source
                deathRecord.setDataSource((DeathDataSource) lookupCacheService.getByCodeFromCache(DeathDataSource.class,
                        form.getDeathNotificationSource()));

                // Death Reporting Site
                deathRecord.setFacilityReceived((VAFacility) lookupCacheService.getByCodeFromCache(VAFacility.class,
                        form.getDeathNotificationSite()));
                /*
                if(Boolean.valueOf(form.getDodVerificationIndicator()).equals(Boolean.TRUE)){
                	deathRecord.setDodVerifiedInd(Boolean.valueOf(form.getDodVerificationIndicator()));
                }
                */
            } else {
                // The DOD is not present. If the death record is not present, leave it that way.
                // Otherwise, blank out the individual fields on it to preserve the lazarus date
                // (i.e. the date that we communicate with the site that says when the DOD is deleted).
                if (deathRecord != null) {
                    deathRecord.setDeathDate(null);
                    deathRecord.setDataSource(null);
                    deathRecord.setFacilityReceived(null);
                    //deathRecord.setDodVerifiedInd(null);
                }
            }

            // Preferred Facility
            // CCR 10640 -- allow multiple preferred facilities
            /*
             * person.setPreferredFacility((VAFacility) lookupCacheService.getByCodeFromCache( VAFacility.class,
             * form.getPreferredFacility()));
             */
            addPreferredFacilitiesToPerson(form, person);

            // Claim Folder
            person.setClaimFolderNumber(form.getClaimFolderNumber());

            if (StringUtils.isNotEmpty(form.getClaimFolderNumber())) {
                if (StringUtils.isNotEmpty(form.getClaimFolderLocation())) {
                    person.setClaimFolderLocation((VAFacility) lookupCacheService.getByCodeFromCache(VAFacility.class,
                            form.getClaimFolderLocation()));
                } else {
                    // If not specified set the default location (376)
                    person.setClaimFolderLocation((VAFacility) lookupCacheService.getByCodeFromCache(VAFacility.class,
                            VAFacility.CODE_DEFAULT_CLAIM_FOLDER_LOCATION.getName()));
                }
            } else {
                person.setClaimFolderLocation(null);
            }

            // Populate Emergency responses.
            this.populateFormToEmergencyReponse(form, person);

            // Marital Status
            person.setMaritalStatus((MaritalStatus) lookupCacheService.getByCodeFromCache(MaritalStatus.class,
                    form.getMaritalStatus()));

            this.convertFormToPersonPreferredLanguage(form, person);

            EmploymentStatus employmentStatus =
                    (EmploymentStatus) lookupCacheService
                            .getByCodeFromCache(EmploymentStatus.class, form.getEmploymentStatus());

            EmploymentStatus onFileEmploymentStatus =
                    (EmploymentStatus) lookupCacheService.getByCodeFromCache(EmploymentStatus.class,
                            form.getOnFileEmploymentStatus());

            if (employmentStatus == null && onFileEmploymentStatus != null) {
                employmentStatus = onFileEmploymentStatus;
            }
            Employment employment = person.getEmployment();

            if (employment == null) {
                // No previous record exists - create new one
                employment = new Employment();
                person.setEmployment(employment);
            }

            employment.setEmploymentStatus(employmentStatus);
            // CCR 10673
            employment.setRetirementDate(DateUtils.getImpreciseDate(form.getRetirementDate()));

            employment.setEmployerName(form.getEmployerName());
            employment.setEmployerPhone(form.getEmployerPhone());
            employment.setOccupation(form.getOccupation());

            boolean isAddAPerson = form.isAddAPerson();

            if (isAddAPerson) {
                person.setReligion((Religion) lookupCacheService.getByCodeFromCache(Religion.class, form.getReligion()));
                this.setApplication(person, form);
                this.setNeedCareDueToAccident(person, form.getNeedCareDueToAccident());
                this.setNeedCareDueToInjury(person, form.getNeedCareDueToInjury());

                if (StringUtils.isNotEmpty(form.getMothersFirstName()) && StringUtils.isNotEmpty(form.getMothersLastName()))
                    this.setMothersName(person, form);
                if (StringUtils.isNotEmpty(form.getFathersFirstName()) && StringUtils.isNotEmpty(form.getFathersLastName()))
                    this.setFathersName(person, form);
                if (StringUtils.isNotEmpty(form.getOtherSsns()))
                    this.setOtherSsns(person, form);
                if (StringUtils.isNotEmpty(form.getOtherFirstNames()) && StringUtils.isNotEmpty(form.getOtherLastNames()))
                    this.setOtherNames(person, form);

                // set employer address
                if (form.isAnyAddressFieldFilled()) {
                    Address address = employment.getEmployerAddress();
                    if (address == null) {
                        address = new Address();
                        employment.setEmployerAddress(address);
                    }
                    // Convert the standard address fields
                    convertFormToAddress(form, address);
                } else {
                    // If no address fields are filled, remove the address object
                    employment.setEmployerAddress(null);
                }

                if (form.getAppointmentRequestResponse().equals("1")) {
                    person.setAppointmentRequestDate(DateUtils.getDate(form.getAppointmentRequestDate()));
                    person.setAppointmentRequestResponse(Boolean.TRUE);
                } else {
                    person.setAppointmentRequestResponse(Boolean.FALSE);
                }
                // TODO alias other first name, last name, other ssn, mulitple values
            }
            // TODO check what needs to be for Read only fields
            /*
             * form.getUserEnrolleeValidthroughDate(); form.getUserEnrolleeSite(); form.getUserEnrolleeSite();
             * form.getAppointmentRequestDate(); form.getAppointmentRequestResponse();
             */
        } catch (Exception ex) {
            throw new ConversionServiceException("Conversion Failed", ex);
        }
    }

    /**
     * Converts the Preferred Language portion of the Form to the Person.
     * @param form the source form
     * @param person the target person
     * @throws UnknownLookupTypeException If errors encountered retrieving the Language.
     * @throws ClassNotFoundException If a coding error exists.
     */
    private void convertFormToPersonPreferredLanguage(DemographicPersonalForm form, Person person)
            throws UnknownLookupTypeException, ClassNotFoundException {

        if (isPreferredLanguageCodeUnchanged(person, form)){
            return;
        }

        if (person.getPreferredLanguage() == null){
            person.setPreferredLanguage(new PreferredLanguage());
        }

        person.getPreferredLanguage().setLanguage((Language) getLookupCacheService().getByCodeFromCache(Language.class,
                form.getPreferredLanguageCode()));

        if (StringUtils.isEmpty(form.getLanguageEntryDate())){
            person.getPreferredLanguage().setLanguageEntryDate(CommonDateUtils.getCurrentDate());
        }
        // TODO: How do we validate the date string entered and message the user to correct the date format?
        else{
            person.getPreferredLanguage().setLanguageEntryDate(CommonDateUtils.getDate(form.getLanguageEntryDate()));
        }
    }

    private boolean isPreferredLanguageCodeUnchanged(Person person, DemographicPersonalForm form) {
        if (person.getPreferredLanguage() != null
                && person.getPreferredLanguage().getLanguage() != null){

            Date formEntryDate = CommonDateUtils.getDate(form.getLanguageEntryDate());
            if (formEntryDate == null)
            {
                  formEntryDate = CommonDateUtils.getCurrentDate();
            }

            return (StringUtils.compareTo(person.getPreferredLanguage().getLanguage().getCode(), form.getPreferredLanguageCode()) == 0 &&
                        CommonDateUtils.isSameDay(person.getPreferredLanguage().getLanguageEntryDate(), formEntryDate));
        }
        return false;
    }


    private void populateFormToEmergencyReponse(DemographicPersonalForm form, Person person) throws ConversionServiceException {
        try {
            Map existingEResponseIndicatorMap = getEmergencyResponseIndicatorMap(person.getEmergencyResponseIndicators());

            // update Emergency Response Indicators
            person.removeAllEmergencyResponseIndicators();
            String[] eResponseCodes = form.getEmergencyResponse();
            if (eResponseCodes != null && eResponseCodes.length > 0) {
                EmergencyResponseIndicator eResponseIndicator = null;
                String eResponseCode = null;
                EmergencyResponse emergencyResponse = null;
                for (int i = 0; i < eResponseCodes.length; i++) {
                    eResponseCode = eResponseCodes[i];
                    if (StringUtils.isNotEmpty(eResponseCode)) {
                        eResponseIndicator = (EmergencyResponseIndicator) existingEResponseIndicatorMap.get(eResponseCode);
                        if (eResponseIndicator == null) {
                            emergencyResponse =
                                    (EmergencyResponse) this.getLookupCacheService().getByCodeFromCache(
                                            EmergencyResponse.class, eResponseCode);
                            if (emergencyResponse != null) {
                                eResponseIndicator = new EmergencyResponseIndicator();
                                eResponseIndicator.setEmergencyResponse(emergencyResponse);
                            }
                        }
                        if (eResponseIndicator != null) {
                            person.addEmergencyResponseIndicator(eResponseIndicator);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            throw new ConversionServiceException("Error while populating emergency response indicators", ex);
        }
    }

    private void populateEmergencyReponseToForm(Person person, DemographicPersonalForm form) throws ConversionServiceException {
        try {
            Set existingEResponseIndicator = person.getEmergencyResponseIndicators();
            if (existingEResponseIndicator != null && !existingEResponseIndicator.isEmpty()) {
                String[] eResponseCode = new String[existingEResponseIndicator.size()];
                EmergencyResponseIndicator eResponseIndicator = null;
                int i = 0;
                for (Iterator iter = existingEResponseIndicator.iterator(); iter.hasNext();) {
                    eResponseIndicator = (EmergencyResponseIndicator) iter.next();
                    if (eResponseIndicator != null) {
                        eResponseCode[i] = eResponseIndicator.getEmergencyResponse().getCode();
                        i = i + 1;
                    }
                }
                form.setEmergencyResponse(eResponseCode);
            }
        } catch (Exception ex) {
            throw new ConversionServiceException("Error while populating emergency response indicators", ex);
        }
    }

    private Map getEmergencyResponseIndicatorMap(Set set) {
        Map map = new HashMap();
        if (set != null) {
            EmergencyResponseIndicator eResponseIndicator = null;
            for (Iterator iter = set.iterator(); iter.hasNext();) {
                eResponseIndicator = (EmergencyResponseIndicator) iter.next();
                map.put(eResponseIndicator.getEmergencyResponse().getCode(), eResponseIndicator);
            }
        }
        return map;
    }

    // Religion
    private String getReligion(Person person) {
        return person.getReligion() == null ? null : person.getReligion().getCode();
        // return person.getReligion()==null ? null : person.getReligion().getName();
    }

    // BenefitAppliedFor
    private String getBenefitAppliedFor(Person person) {
        Application app = person.getApplication();
        String benefitType = null;

        if (app != null) {
            benefitType = app.getBenefitType() == null ? null : app.getBenefitType().getCode();
            // benefitType = app.getBenefitType()==null ? null : app.getBenefitType().getName();
        }
        return benefitType;
    }

    private List getOtherFirstNames(Person person) {

        Set otherNames = new HashSet(person.getOtherNames());
        List otherFirstNames = new ArrayList();

        if (otherNames != null && otherNames.size() > 0) {
            Object otherNamesArray[] = otherNames.toArray();

            for (int i = 0; i < otherNamesArray.length; i++) {
                otherFirstNames.add(((Name) otherNamesArray[i]).getGivenName());
            }
        }
        return otherFirstNames;
    }

    private List getOtherLastNames(Person person) {

        Set otherNames = new HashSet(person.getOtherNames());
        List otherLastNames = new ArrayList();

        if (otherNames != null && otherNames.size() > 0) {
            Object otherNamesArray[] = otherNames.toArray();

            for (int i = 0; i < otherNamesArray.length; i++) {
                otherLastNames.add(((Name) otherNamesArray[i]).getFamilyName());
            }
        }
        return otherLastNames;
    }

    private void setNeedCareDueToAccident(Person person, String setYes) {
        if (setYes == null || setYes.equalsIgnoreCase(ConvertUtils.NULL_VALUE)) {
            person.setNeedCareDueToAccident(null);
        } else {
            person.setNeedCareDueToAccident(ConvertUtils.convertBoolean(setYes));
        }
    }

    private void setNeedCareDueToInjury(Person person, String setYes) {
        if (setYes == null || setYes.equalsIgnoreCase(ConvertUtils.NULL_VALUE)) {
            person.setNeedCareDueToInjury(null);
        } else {
            person.setNeedCareDueToInjury(ConvertUtils.convertBoolean(setYes));
        }
    }

    private void setApplication(Person person, DemographicPersonalForm form) throws Exception {
        LookupCacheService lookupCacheService = getLookupCacheService();
        Application a = person.getApplication();
        if (a == null) {
            a = new Application();
            a.setPerson(person);
            person.setApplication(a);
        }
        a.setBenefitType((BenefitType) lookupCacheService.getByCodeFromCache(BenefitType.class, form.getBenefitAppliedFor()));
    }

    private void setMothersName(Person person, DemographicPersonalForm form) throws Exception {
        LookupCacheService lookupCacheService = getLookupCacheService();
        Relation mother = person.getMother();
        if (mother == null) {
            mother = new Relation();
            mother.setRelationship((Relationship) lookupCacheService.getByCodeFromCache(Relationship.class,
                    Relationship.CODE_MOTHER.getCode()));
            mother.setPerson(person);
            person.setRelation(Relationship.CODE_MOTHER.getCode(), mother);
        }
        Name mothersName = new Name();
        mothersName.setGivenName(form.getMothersFirstName());
        mothersName.setFamilyName(form.getMothersLastName());
        mother.setName(mothersName);
        person.setMothersName(mothersName);
    }

    private void setFathersName(Person person, DemographicPersonalForm form) throws Exception {
        LookupCacheService lookupCacheService = getLookupCacheService();
        Relation father = person.getFather();
        if (father == null) {
            father = new Relation();
            father.setPerson(person);
            father.setRelationship((Relationship) lookupCacheService.getByCodeFromCache(Relationship.class,
                    Relationship.CODE_FATHER.getCode()));
            person.setRelation(Relationship.CODE_FATHER.getCode(), father);
        }
        Name fathersName = new Name();
        fathersName.setGivenName(form.getFathersFirstName());
        fathersName.setFamilyName(form.getFathersLastName());
        father.setName(fathersName);
        person.setFathersName(fathersName);
    }

    private void setOtherNames(Person person, DemographicPersonalForm form) throws ConversionServiceException {
        try {
            LookupCacheService lookupCacheService = getLookupCacheService();
            Set otherNames = person.getOtherNames();
            if (otherNames != null) {
                for (Iterator i = otherNames.iterator(); i.hasNext();) {
                    person.removeName((Name) i.next());
                }
            }
            String frmOtherFirstNames = form.getOtherFirstNames();
            String frmOtherLastNames = form.getOtherLastNames();
            StringTokenizer otherLastToken = new StringTokenizer(frmOtherLastNames);
            StringTokenizer otherFirstToken = new StringTokenizer(frmOtherFirstNames);

            // ArrayList otherNamesArray = new ArrayList();
            while (otherLastToken.hasMoreTokens() && otherFirstToken.hasMoreTokens()
                    && otherLastToken.countTokens() == otherFirstToken.countTokens()) {
                String oLastName = otherLastToken.nextToken();
                String oFirstName = otherFirstToken.nextToken();
                Name oName = new Name();
                oName.setGivenName(oFirstName);
                oName.setFamilyName(oLastName);
                oName.setType((NameType) lookupCacheService.getByCodeFromCache(NameType.class, NameType.ALIAS_NAME.getName()));
                person.addName(oName);
                // otherNamesArray.add((Name)oName);
            }
            /*
             * for (Iterator i = otherNamesArray.iterator(); i.hasNext();) { Name lname = (Name)i.next();
             * lname.setType((NameType)lookupCacheService.getByCodeFromCache(NameType.class, NameType.ALIAS_NAME.getName()));
             * person.addName(lname); }
             */
        } catch (Exception ex) {
            throw new ConversionServiceException("Conversion Failed", ex);
        }
    }

    private void setOtherSsns(Person person, DemographicPersonalForm form) throws ConversionServiceException {
        try {
            LookupCacheService lookupCacheService = getLookupCacheService();
            Set otherSsns = person.getOtherSsns();
            if (otherSsns != null)
                person.removeOtherSsns(otherSsns);

            String fmOtherSsns = form.getOtherSsns();
            StringTokenizer otherSsnTokesn = new StringTokenizer(fmOtherSsns);
            // ArrayList otherSsnArray = new ArrayList();

            while (otherSsnTokesn.hasMoreTokens()) {
                String oSsnStr = otherSsnTokesn.nextToken();
                SSN oSsn = new SSN();
                oSsn.setSsnText(oSsnStr);
                oSsn.setType((SSNType) lookupCacheService.getByCodeFromCache(SSNType.class, SSNType.CODE_ALIAS.getName()));
                person.addSsn(oSsn);
                // otherSsnArray.add(otherSsnTokesn.nextToken());
            }
        } catch (Exception ex) {
            throw new ConversionServiceException("Conversion Failed", ex);
        }
    }

    private String displayValues(List values, String defText, String format) {
        StringBuffer result = new StringBuffer();
        for (Iterator i = values.iterator(); i.hasNext();) {
            result.append(JspUtils.displayValue(i.next(), defText, format));
            result.append(i.hasNext() ? NAME_BREAK : "");
        }
        return result.toString();
    }

    /**
     * Adds the list of preferredFacilities to the form.
     *
     * @param preferredFacilities
     *            The list of PreferredFacility objects.
     * @param form
     *            The form to add the preferredFacilities to.
     */
    protected void addPreferredFacilitiesToForm(List preferredFacilities, DemographicPersonalForm form) {
        for (Iterator iterator = preferredFacilities.iterator(); iterator.hasNext();) {
            PreferredFacility pf = (PreferredFacility) iterator.next();

            // add the preferred facility
            String pfID = null;
            if (pf.getEntityKey() == null)
                pfID = "";
            else
                pfID = pf.getEntityKey().getKeyValueAsString();

            form.addPreferredFacility(pfID, getLookupCode(pf.getFacility()), getLookupCode(pf.getSourceDesignation()));
        }

        // if there are no existing prefered facilities, the user will have to enter a new one
        if (form.getPreferredFacilitySize() == 0) {
            form.addNewPreferredFacility();
        }
    }

    protected void addPreferredFacilitiesToPerson(DemographicPersonalForm form, Person person)
            throws ConversionServiceException {
        LookupCacheService lookupCacheService = getLookupCacheService();

        try {
            // Update/delete/add Preferred Facilities
            List remainingPfs = new ArrayList();
            List pfIds = form.getPreferredFacilityIds();
            if (pfIds != null && !pfIds.isEmpty()) {
                for (int i = 0; i < pfIds.size(); i++) {
                    // Only add/keep the preferredFacility if the site isn't empty
                    String site = form.getPreferredFacilitySite(i);
                    if (StringUtils.isNotBlank(site)) {
                        PreferredFacility preferredFacility = null;
                        String pfId = (String) pfIds.get(i);

                        // The preferredFacility should already be defined on the Person
                        if (StringUtils.isNotEmpty(pfId)) {
                            preferredFacility =
                                    person.getPreferredFacilityByEntityKey(CommonEntityKeyFactory
                                            .createPreferredFacilityEntityKey(pfId));
                        }

                        // If the preferredFacility isn't associated with the person, create it as a new one
                        if (preferredFacility == null) {
                            preferredFacility = new PreferredFacility();
                        }
                        remainingPfs.add(preferredFacility);

                        // Overlay other form data on top of the PreferredFacility object.

                        // Facility station number
                        if (StringUtils.isNotEmpty(form.getPreferredFacilitySite(i))) {
                            preferredFacility.setFacility((VAFacility) lookupCacheService.getByCodeFromCache(VAFacility.class,
                                    form.getPreferredFacilitySite(i)));
                        }

                        // Source Designation
                        if (StringUtils.isNotEmpty(form.getPreferredFacilitySD(i))) {
                            preferredFacility.setSourceDesignation((SourceDesignation) lookupCacheService.getByCodeFromCache(
                                    SourceDesignation.class, form.getPreferredFacilitySD(i)));
                        }

                    }
                }

                // Update the preferredFacilities on the Person
                person.removeAllPreferredFacilities();
                for (Iterator iterator = remainingPfs.iterator(); iterator.hasNext();) {
                    PreferredFacility pf = (PreferredFacility) iterator.next();
                    person.addPreferredFacility(pf);
                }
            }
        } catch (Exception ex) {
            throw new ConversionServiceException("Unable to convert DemographicPersonalForm to Person.", ex);
        }

    }

}
