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

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

import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.comms.DeliveryPreference;

import gov.va.med.esr.common.model.lookup.DeliveryPreferenceType;
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.id.PersonEntityKey;
import gov.va.med.esr.common.model.person.id.VPIDEntityKeyImpl;

import gov.va.med.esr.service.ClinicalDeterminationService;
import gov.va.med.esr.service.CommsEmailBulletinService;
import gov.va.med.esr.service.DemographicService;
import gov.va.med.esr.service.EligibilityEnrollmentService;
import gov.va.med.esr.service.HandBookService;
import gov.va.med.esr.service.HistoricalInfoService;
import gov.va.med.esr.service.LookupService;

import gov.va.med.esr.service.PersonSearchQueryInfo;
import gov.va.med.esr.service.PreferredFacilityService;
import gov.va.med.esr.service.external.ESRException;
import gov.va.med.esr.service.external.EntityFinder;
import gov.va.med.esr.service.external.ExternalHandBookFactory;
import gov.va.med.esr.service.external.ExternalServiceBean;
import gov.va.med.esr.service.external.ExternalSummaryFactory;
import gov.va.med.esr.service.external.HandBookRequestInfo;
import gov.va.med.esr.service.external.person.AbstractEntityFinder;

import gov.va.med.esr.service.external.person.CategoryInfo;
import gov.va.med.esr.service.external.person.DeliveryPreferenceInfo;

import gov.va.med.esr.service.external.person.EDIPIEntityFinder;
import gov.va.med.esr.service.external.person.EESummary;

import gov.va.med.esr.service.external.person.EligibilitySummary;
import gov.va.med.esr.service.external.person.EnrollmentDeterminationInfo;

import gov.va.med.esr.service.external.person.IVMLastPolledEntityFinder;
import gov.va.med.esr.service.external.person.IVMRecordStatusEntityFinder;
import gov.va.med.esr.service.external.person.IVMSummary;

import gov.va.med.esr.service.external.person.LNSEntityFinder;
import gov.va.med.esr.service.external.person.MSSummary;
import gov.va.med.esr.service.external.person.PersonLinkInfo;
import gov.va.med.esr.service.external.person.PersonMoveInfo;
import gov.va.med.esr.service.external.person.PersonPrimaryViewInfo;
import gov.va.med.esr.service.external.person.PersonServiceUtil;

import gov.va.med.esr.service.external.person.SSNEntityFinder;
import gov.va.med.esr.service.external.person.SimpleEligibilitySummary;
import gov.va.med.esr.service.external.person.VPIDEntityFinder;
import gov.va.med.esr.service.external.person.VPIDEntityKey;
import gov.va.med.esr.service.external.person.collections.CategoryCollection;

import gov.va.med.esr.service.impl.ChangeEvent;
import gov.va.med.esr.service.impl.IdmWebServiceDelegate;
import gov.va.med.esr.service.trigger.BulletinTrigger;

import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.ps.model.PatientIdentifier;

import java.io.Serializable;
import java.math.BigDecimal;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;


import javax.security.auth.login.LoginException;

import org.hibernate.exception.ExceptionUtils;


/**
 * Initial javadoc for class PersonServiceBean. TODO - Add content here
 *
 * Created Jan 3, 2006 3:34:23 PM
 *
 * @author DNS   BOHMEG
 */
public class PersonServiceBean extends ExternalServiceBean implements
		gov.va.med.esr.service.external.person.PersonService {
	/**
	 *
	 */
	private static final long serialVersionUID = 7424028798090596846L;
    private static final String ELIGIBILITY = "ELIGIBILITY";
    private static final String ENROLLMENT = "ENROLLMENT";
    private static final String DISABILITY = "DISABILITY";
    private static final String INSURANCE = "INSURANCE";
    private static final String ACA_MEC = "ACA_MEC";
    private static final String ACA_MEC_START = "ACA_MEC_START";
    private static final String ACA_MEC_END = "ACA_MEC_END";
    private static final String ALL = "ALL";

	private EligibilityEnrollmentService eeService;

	private gov.va.med.esr.service.PersonService personService;

	private ExternalSummaryFactory externalSummaryFactory;

	private ExternalHandBookFactory externalHandBookFactory;
    private ClinicalDeterminationService clinicalDeterminationService;
    private DemographicService demographicService;
    private PreferredFacilityService preferredFacilityService;
    private HistoricalInfoService historicalInfoService;
   // private InsuranceService insuranceService;
    private HandBookService handBookService;
    private CommsEmailBulletinService commsEmailBulletinService;
    private IdmWebServiceDelegate idmServiceDelegate = null;
    private LookupService lookupService = null;


	/*
	 * (non-Javadoc)
	 *
	 * @see gov.va.med.esr.service.external.person.PersonService#link(gov.va.med.esr.service.external.person.VPIDEntityKey,
	 *      gov.va.med.esr.service.external.person.VPIDEntityKey)
	 */
	public void link(VPIDEntityKey deprecatedVPID, VPIDEntityKey survivingVPID)
			throws ESRException {
		try {
			processAuthenticate(PersonLinkInfo.DEFAULT_MESSAGE_INITIATER);
			Serializable data = PersonServiceUtil.createLinkInfo(
					deprecatedVPID, survivingVPID);
			publishExternalEventForInternalProcessing(
					PersonLinkInfo.DEFAULT_MESSAGE_TYPE, data);
		} catch (Exception e) {
			throw new ESRException("Unable to trigger event for: "
					+ PersonLinkInfo.DEFAULT_MESSAGE_TYPE, e);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see gov.va.med.esr.service.external.person.PersonService#move(java.lang.String,
	 *      java.lang.String,
	 *      gov.va.med.esr.service.external.person.VPIDEntityKey,
	 *      gov.va.med.esr.service.external.person.VPIDEntityKey)
	 */
	public void move(String dfn, String stationNumber, VPIDEntityKey fromVpid,
			VPIDEntityKey toVpid) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
			Serializable data = PersonServiceUtil.createMoveInfo(dfn,
					stationNumber, fromVpid, toVpid);
			publishExternalEventForInternalProcessing(
					PersonMoveInfo.DEFAULT_MESSAGE_TYPE, data);
		} catch (Exception e) {
			throw new ESRException("Unable to trigger event for: "
					+ PersonMoveInfo.DEFAULT_MESSAGE_TYPE, e);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see gov.va.med.esr.service.external.person.PersonService#move(java.lang.String,
	 *      java.lang.String,
	 *      gov.va.med.esr.service.external.person.VPIDEntityKey,
	 *      gov.va.med.esr.service.external.person.VPIDEntityKey)
	 */
	public void primaryviewUpdate(VPIDEntityKey vpid) throws ESRException {
		try {
			processAuthenticate(PersonPrimaryViewInfo.DEFAULT_MESSAGE_INITIATER);
			Serializable data = PersonServiceUtil.createPrimaryViewInfo(vpid);
			publishExternalEventForInternalProcessing(
					PersonPrimaryViewInfo.DEFAULT_MESSAGE_TYPE, data);
		} catch (Exception e) {
			throw new ESRException("Unable to trigger event for: "
					+ PersonPrimaryViewInfo.DEFAULT_MESSAGE_TYPE, e);
		}
	}


	/*
	 * (non-Javadoc)
	 *
	 * @see gov.va.med.esr.service.external.person.PersonService#getEligibilitySummary(gov.va.med.esr.service.external.person.VPIDEntityKey)
	 */
	public EligibilitySummary getEligibilitySummary(VPIDEntityKey vpid)
			throws ESRException {
		try {
			return getEligibilityEnrollmentService()
					.getEligibilitySummary(vpid);
		} catch (Exception e) {
			throw new ESRException(
					"Unable to get Eligibility Summary for VPID: "
							+ vpid.getVPID(), e);
		}
	}

	private EligibilityEnrollmentService getEligibilityEnrollmentService() {
		if (eeService == null) {
			eeService = (EligibilityEnrollmentService) getBeanFactory()
					.getBean(EligibilityEnrollmentService.class.getName(),
							EligibilityEnrollmentService.class);
		}
		return eeService;
	}

    private DemographicService getDemographicService() {
        if (demographicService == null) {
            demographicService = (DemographicService) getBeanFactory()
                    .getBean("demographicService");
        }
        return demographicService;
    }

    private PreferredFacilityService getPreferredFacilityService() {
        if (preferredFacilityService == null) {
        	preferredFacilityService = (PreferredFacilityService) getBeanFactory()
                    .getBean("preferredFacilityService");
        }
        return preferredFacilityService;
    }

    private ClinicalDeterminationService getClinicalDeterminationService() {
        if (clinicalDeterminationService == null) {
            clinicalDeterminationService = (ClinicalDeterminationService) getBeanFactory()
                    .getBean("clinicalDeterminationService");
        }
        return clinicalDeterminationService;
    }



	/**
	 * API for Canteen System to get the veteran indicator
	 *
	 * @param ssn
	 * @return {@link SimpleEligibilitySummary}
	 * @throws ESRException
	 */
	public SimpleEligibilitySummary getSimpleEligibilitySummary(String ssn)
			throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
		} catch (LoginException le) {
			throw new ESRException(
					"Unable to Search getSimpleEligibilitySummary", le);
		}
		PersonSearchQueryInfo searchQueryInfo = new PersonSearchQueryInfo();
		searchQueryInfo.setUnformattedSsn(ssn);

		List persons = null;

		try {
			persons = getPersonService().search(searchQueryInfo, true, false,
					false, -1);
		} catch (ServiceException se) {
			throw new ESRException(
					"Unable to Search getSimpleEligibilitySummary", se);
		}

		if (persons == null || persons.size() <= 0) {
			return null;
		}

		if (persons.size() > 1) {
			throw new ESRException("More Than one person found with this SSN");
		}

		SimpleEligibilitySummary summary = new SimpleEligibilitySummary();

		Person person = (Person) persons.get(0);
		// summary.setFirstName(perso)
		// person.getIdentityTraits().getLegalName();

		Boolean veteranInd = person.isVeteran();
		if (veteranInd == null) {
			veteranInd = new Boolean(false);
		}
		summary.setVeteranIndicator(veteranInd);
		Name legalName = person.getIdentityTraits().getLegalName();
		summary.setFirstName(legalName.getGivenName());
		summary.setLastName(legalName.getFamilyName());
		summary.setMiddleName(legalName.getMiddleName());
		return summary;
	}



	public EESummary getEESummary(EntityFinder finder) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
			AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
			processAuthorize(personFinder.getAccountName(), personFinder.getRequestName());
			EESummary eeSummary = getExternalSummaryFactory().buildEESummary(getPersonFromFinder(finder, "eeSummary"),personFinder.getIncomeYear(),personFinder.getRequestName());
			if(eeSummary != null)
				{
				getEEAdminService().applyRequest(eeSummary,	personFinder.getAccountName(), personFinder.getRequestName());
				}
			return eeSummary;
		} catch (Exception e) {

			String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}
			logger.error("Exception in getEESummary for finder :"
					+ finderData //finder.getFinderData()
					, e);
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);
			throw new ESRException(
					"Unable to invoke service with EntityFinder arg: "
							+ finderData //finder.getFinderData()
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

    public EESummary getEESummaryHistory(EntityFinder finder) throws ESRException {
        try {

            processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
            AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
            processAuthorize(personFinder.getAccountName(), personFinder
                    .getRequestName());
            PersonEntityKey personEntityKey =
                CommonEntityKeyFactory.createPersonIdEntityKey(getPersonFromFinder(finder).getEntityKey().getKeyValueAsString());

            EESummary eeSummary = new EESummary();
            EnrollmentDeterminationInfo edInfo = new EnrollmentDeterminationInfo();
            eeSummary.setEnrollmentDeterminationInfo(edInfo);
            CategoryCollection categorys = personFinder.getCategories();
            ChangeEvent ce = new ChangeEvent(personEntityKey);
            Date acaStart = null;
            Date now = new Date();
            Date acaEnd = null;
            if(categorys != null){
                 CategoryInfo[] catinfo = categorys.getCategory();
                 for(int i=0; i < catinfo.length; i = i+1){

                     ce.getTimeStamp().setTime(catinfo[i].getDateOfService().getTime());

                     if(catinfo[i].getCategoryName().equalsIgnoreCase(ELIGIBILITY) ||catinfo[i].getCategoryName().equalsIgnoreCase(ALL) ){
                        getExternalSummaryFactory().buildEESummaryHistory(
                                (Person)getEligibilityEnrollmentService()
                                .getEligibilityHistoryByChangeTime(ce).getCurrentVersion(),
                                eeSummary,ELIGIBILITY, null, null);
                    }
                     if(catinfo[i].getCategoryName().equalsIgnoreCase(ENROLLMENT) || catinfo[i].getCategoryName().equalsIgnoreCase(ALL)){

                         getExternalSummaryFactory().buildEESummaryHistory(
                                 (Person)getEligibilityEnrollmentService()
                                 .getEnrollmentHistoryByChangeTime(ce).getCurrentVersion(),
                                 eeSummary,ENROLLMENT, null, null);
                         //to get primary eligibility and ineligibility factor
                         getExternalSummaryFactory().buildEESummaryHistory(
                                 (Person)getEligibilityEnrollmentService()
                                 .getEligibilityHistoryByChangeTime(ce).getCurrentVersion(),
                                 eeSummary,"PRIMARYELIGIBILITY", null, null);
                    }
                     if(catinfo[i].getCategoryName().equalsIgnoreCase(INSURANCE)|| catinfo[i].getCategoryName().equalsIgnoreCase(ALL)){

                     if(this.getDemographicService() != null){
                         getExternalSummaryFactory().buildEESummaryHistory(
                                 (Person)getDemographicService().getInsuranceHistoryByChangeTime(ce)
                                 .getCurrentVersion(),
                                 eeSummary,INSURANCE, null, null);
                     }
                     }
                     if(catinfo[i].getCategoryName().equalsIgnoreCase(DISABILITY) || catinfo[i].getCategoryName().equalsIgnoreCase(ALL)){

                         getExternalSummaryFactory().buildEESummaryHistory(
                                 (Person)getEligibilityEnrollmentService()
                                 .getEligibilityHistoryByChangeTime(ce).getCurrentVersion(),
                                 eeSummary,DISABILITY, null, null);
                    }
                     //WI 324899 MEC Period ACA coverage period by date
	                 if(catinfo[i].getCategoryName().equalsIgnoreCase(ACA_MEC_START)) {
	                	 acaStart = catinfo[i].getDateOfService();
	                }
	                 if(catinfo[i].getCategoryName().equalsIgnoreCase(ACA_MEC_END)) {
	                	 acaEnd = catinfo[i].getDateOfService();
	                }
                 }

                 if (acaStart != null && acaEnd != null && acaEnd.before(acaStart)) {
                	 throw new ESRException("Invalid Service Category Dates: End Date Before Start Date");
                 }

                 if ((acaStart != null && acaStart.after(now)) || (acaEnd != null && acaEnd.after(now))) {
                	 throw new ESRException("Invalid Date Of Service Parameter: Date Cannot Be In The Future");
                 }

                 if (acaStart != null || acaEnd != null) {
                	 getExternalSummaryFactory().buildEESummaryHistory(
                		 getPersonFromFinder(finder), eeSummary,ACA_MEC, acaStart, acaEnd);
                 }

            }
            if(eeSummary != null){

            getEEAdminService().applyRequest(eeSummary,
                    personFinder.getAccountName(),
                   personFinder.getRequestName());
            }

            return eeSummary;

        } catch (Exception e) {

        	String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}
            logger.error("Exception in getEESummary for finder :"
                    + finderData //finder.getFinderData()
                    , e);
            String[] rootCauseStackTrace = ExceptionUtils
                    .getRootCauseStackTrace(e);
            throw new ESRException(
                    "Unable to invoke service with EntityFinder arg: "
                            + finderData //finder.getFinderData()
                            + " due to exception message: " + e.getMessage()
                            + " and root cause stack trace: "
                            + rootCauseStackTrace[0]);
        }
    }


    public EESummary getEDStatus(EntityFinder finder) throws ESRException {
        try {
            processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
            EESummary eeSummary = getExternalSummaryFactory().buildEDStatus(
                    getPersonFromFinder(finder));
           /*
            getEEAdminService().applyRequest(eeSummary,
                    personFinder.getAccountName(),
                   personFinder.getRequestName());
            */
            return eeSummary;
        } catch (Exception e) {

        	String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}
            logger.error("Exception in getEESummary for finder :"
                    + finderData //finder.getFinderData()
                    , e);
            String[] rootCauseStackTrace = ExceptionUtils
                    .getRootCauseStackTrace(e);
            throw new ESRException(
                    "Unable to invoke service with EntityFinder arg: "
                            + finderData //finder.getFinderData()
                            + " due to exception message: " + e.getMessage()
                            + " and root cause stack trace: "
                            + rootCauseStackTrace[0]);
        }
    }

    public EESummary getPersonNotificationStatus(EntityFinder finder) throws ESRException {
        try {
            processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
            EESummary eeSummary = new EESummary();
            VPIDEntityFinder personFinder = (VPIDEntityFinder) finder;

            if(personFinder.getNotificationType() != null){
            		if(personFinder.getNotificationType().equalsIgnoreCase("PrimaryViewUpdate")){
            		//
            			 if(isValidforPrimaryviewUpdate(getPersonFromFinder(finder))){
            				 primaryviewUpdate(gov.va.med.esr.service.external.person.EntityKeyFactory.createVPIDEntityKey(personFinder.getVpid()));
            			 }
            		}
            		if(personFinder.getNotificationType().equalsIgnoreCase("Link")){
            		//
            		link(gov.va.med.esr.service.external.person.EntityKeyFactory.createVPIDEntityKey(personFinder.getSurvivingVpid()),
            				gov.va.med.esr.service.external.person.EntityKeyFactory.createDeprecatedVPIDEntityKey(personFinder.getDeprecatedVpid()));
            		}
            		if(personFinder.getNotificationType().equalsIgnoreCase("Move")){
            		//
            		move(personFinder.getDfn(),personFinder.getStationName(),
            				gov.va.med.esr.service.external.person.EntityKeyFactory.createVPIDEntityKey(personFinder.getFromVpid()),
            				gov.va.med.esr.service.external.person.EntityKeyFactory.createVPIDEntityKey(personFinder.getToVpid()));
            		}
            }

            return eeSummary;
        } catch (Exception e) {

        	String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}

            logger.error("Exception in getEESummary for finder :"
                    + finderData //finder.getFinderData()
                    , e);
            String[] rootCauseStackTrace = ExceptionUtils
                    .getRootCauseStackTrace(e);
            throw new ESRException(
                    "Unable to invoke service with EntityFinder arg: "
                            + finderData //finder.getFinderData()
                            + " due to exception message: " + e.getMessage()
                            + " and root cause stack trace: "
                            + rootCauseStackTrace[0]);
        }
    }

    public EESummary getDeliveryPreference(EntityFinder finder) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
			String personId = getPersonFromFinder(finder).getPersonEntityKey().getKeyValueAsString();
			EESummary eeSummary = getExternalHandBookFactory().buildDeliveryPreferenceInfo(getHandBookService().findDeliveryPreferenceByPersonId(personId));
			//As per ccr 12068 these changes applied
			//if(eeSummary.getDeliveryPreferenceInfo() != null){
				if(getHandBookService().findDeliveryPreferenceEditableStatusByPersonId(personId).size()==0 ||
						getHandBookService().findDeliveryPreferenceEditableStatusByPersonId(personId) == null){
					eeSummary.getDeliveryPreferenceInfo().setEditableFlag(Boolean.FALSE);
				}
				else{
						eeSummary.getDeliveryPreferenceInfo().setEditableFlag(Boolean.TRUE);
					}
			//}
			return eeSummary;
		} catch (Exception e) {

        	String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}

			logger.error("Exception in getEESummary for finder :"
					+ finderData //finder.getFinderData()
					, e);
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);
			throw new ESRException(
					"Unable to invoke service with EntityFinder arg: "
							+ finderData //finder.getFinderData()
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

    public EESummary updateDeliveryPreference(EntityFinder finder) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
			AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
			Person person = getPersonFromFinder(finder);
			String personId = person.getPersonEntityKey().getKeyValueAsString();
			EESummary eeSummary = new EESummary();
			////As per ccr 12068 these changes applied
				if(getHandBookService().findDeliveryPreferenceEditableStatusByPersonId(personId).size()==0 ||
						getHandBookService().findDeliveryPreferenceEditableStatusByPersonId(personId) == null){
					eeSummary = null;
				}
				else{
					DeliveryPreferenceInfo info = personFinder.getDeliveryPreferenceInfo();
					DeliveryPreference deliveryPreference = getHandBookService().findDeliveryPreferenceByPersonId(personId);
				//added for ccr 12229
					DeliveryPreference dp = null;
					if (deliveryPreference == null){
						deliveryPreference = new DeliveryPreference();
						person.addDeliveryPreference(deliveryPreference);
						deliveryPreference.setPersonId(new BigDecimal(personId));
						deliveryPreference.setDeliveryPreferenceType((DeliveryPreferenceType)this.getLookupService().getByCode(DeliveryPreferenceType.class, DeliveryPreferenceType.CODE_MAIL.getCode()));

				       }
					    deliveryPreference.setPersonId(new BigDecimal(personId));
						dp = (DeliveryPreference)deliveryPreference.clone();
					//	getExternalHandBookFactory().buildDeliveryPreference(info,dp);
						getHandBookService().buildDeliveryPreference(info, dp);

						//deliveryPreference.setPersonId(new BigDecimal(personId));
						//deliveryPreference.getSourceOfChange().setCode(DeliveryPreferenceSourceOfChange.CODE_VSS.getCode());

						getHandBookService().saveDeliveryPreference(dp);
						//Code for sending email the delivery preference
						sendEmail(info,deliveryPreference);

					}
			return eeSummary;
		} catch (Exception e) {

        	String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}

			logger.error("Exception in getEESummary for finder :"
					+ finderData //finder.getFinderData()
					, e);
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);
			throw new ESRException(
					"Unable to invoke service with EntityFinder arg: "
							+ finderData //finder.getFinderData()
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

	public MSSummary getMSSummary(EntityFinder finder) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
			return getExternalSummaryFactory().buildMSSummary(
					getPersonFromFinder(finder));
		} catch (Exception e) {
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);

        	String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}

			throw new ESRException(
					"Unable to invoke service with EntityFinder arg: "
							+ finderData //finder.getFinderData()
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

	public List getHandBook(EntityFinder finder, HandBookRequestInfo hbReqInfo)
			throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
			return getExternalHandBookFactory().buildHandBookInfo(
					getPersonFromFinder(finder), hbReqInfo);
		} catch (Exception e) {
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);

        	String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}

			throw new ESRException(
					"Unable to invoke service with EntityFinder arg: "
							+ finderData //finder.getFinderData()
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

	public List getHBDataString(EntityFinder finder,
			HandBookRequestInfo hbReqInfo) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.DEFAULT_MESSAGE_INITIATER);
			return getExternalHandBookFactory().buildHBDataString(
					getPersonFromFinder(finder), hbReqInfo);
		} catch (Exception e) {
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);

        	String finderData = "";
			if (finder != null && finder instanceof AbstractEntityFinder) {
				AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
				finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
			}

			throw new ESRException(
					"Unable to invoke service with EntityFinder arg: "
							+ finderData //finder.getFinderData()
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

	public IVMSummary retrieveIVMCandidates(EntityFinder finder) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.IVM_MESSAGE_INITIATER);
			IVMLastPolledEntityFinder candidateFinder = (IVMLastPolledEntityFinder) finder;
			Date date = candidateFinder.getLastPolledDateTimeStamp();
			return getExternalSummaryFactory().buildIVMCandidates(date);
		} catch (Exception e) {
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);

			throw new ESRException(
					"Unable to invoke service "
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

	public IVMSummary retrieveIVMLetterCandidates() throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.IVM_MESSAGE_INITIATER);
			return getExternalSummaryFactory().buildIvmLetterCandidates();
		} catch (Exception e) {
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);

			throw new ESRException(
					"Unable to invoke service "
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

	public IVMSummary updateIVMStatus(EntityFinder finder) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.IVM_MESSAGE_INITIATER);
			IVMRecordStatusEntityFinder updateRecordFinder = (IVMRecordStatusEntityFinder) finder;
			String status = updateRecordFinder.getErrorText();
			BigDecimal transactionId = new BigDecimal(updateRecordFinder.getTransactionId());
			return getExternalSummaryFactory().updateIvmStatus(transactionId, status);
		} catch (Exception e) {
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);

			throw new ESRException(
					"Unable to invoke service "
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}

	public IVMSummary processIVMIncomeTest(EntityFinder finder) throws ESRException {
		try {
			processAuthenticate(PersonMoveInfo.IVM_MESSAGE_INITIATER);
			//TODO change this to the new entity finder created by Tonte if needed
			AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
			return getExternalSummaryFactory().processIVMIncomeTest(getPersonFromFinder(finder), personFinder.getIncomeYear(), personFinder.getSendIVMInfo(),
					personFinder.getIVMLetterInfo());
		} catch (Exception e) {
			String[] rootCauseStackTrace = ExceptionUtils
					.getRootCauseStackTrace(e);

			throw new ESRException(
					"Unable to invoke service "
							+ " due to exception message: " + e.getMessage()
							+ " and root cause stack trace: "
							+ rootCauseStackTrace[0]);
		}
	}



	protected Person getPersonFromFinder(EntityFinder finder)
			throws ServiceException, ESRException {
		Person person = null;
		if (finder instanceof VPIDEntityFinder) {
			// get mode
			gov.va.med.esr.common.model.person.id.VPIDEntityKey internalVpid = CommonEntityKeyFactory.createVPIDEntityKey(finder.getFinderData());


			//	person = getPersonService().getPerson(internalVpid);

            person = getPersonService().getPersonWithoutIdentityTraits(internalVpid);

		} else {
			// search mode
			PersonSearchQueryInfo searchQueryInfo = new PersonSearchQueryInfo();
			if (finder instanceof SSNEntityFinder) {
				searchQueryInfo.setUnformattedSsn(finder.getFinderData());
			} else if (finder instanceof LNSEntityFinder) {
				/*
				 * TODO: talk to PSIM on how to support this commonly used
				 * legacy approach
				 */
				throw new ESRException("LNS person finder not yet implemented");
			}

			List persons = getPersonService().search(searchQueryInfo, true,
					false, false, -1);

			if (persons == null || persons.size() <= 0) {
				return null;
			}

			if (persons.size() > 1) {
				throw new ESRException(
						"More than one person found with provided input");
			}
			person = (Person) persons.get(0);
		}
		return person;
	}

	protected Person getPersonFromFinder(EntityFinder finder, String operationName)
	throws ServiceException, ESRException {
		Person person = null;

    	String finderData = "";
		if (finder != null && finder instanceof AbstractEntityFinder) {
			AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;
			finderData = "" + personFinder.getAccountName() + ":" + personFinder.getRequestName();
		}

//		added CCR 12025-- Input is EDIPI
		if (finder instanceof EDIPIEntityFinder) {
			//call ivm to get VPID
				if (StringUtils.isEmpty(finder.getFinderData()))
					throw new ServiceException("EDIPI Exception :  "
							+ finderData //finder.getFinderData()
							);

				List correlations = this.getIdmServiceDelegate().getCorrelationsByFullyQualifiedIdentifier(finder.getFinderData());
				// Person Not found
				if (correlations == null || correlations.size() == 0) {
					throw new ServiceException("No Record Found from MVI with EDIPI: "
							+ finderData //finder.getFinderData()
							);
				}else{
					//	ESR internally needs long vpid because person table supports only long vpid

					String vpid = VPIDEntityKeyImpl.getLongVPID(getICN(correlations));

					gov.va.med.esr.common.model.person.id.VPIDEntityKey internalVpid = CommonEntityKeyFactory.createVPIDEntityKey(vpid);
					person = getPersonService().getPersonWithoutIdentityTraits(internalVpid);
			}

		}else if (finder instanceof VPIDEntityFinder) {
			// get mode
			gov.va.med.esr.common.model.person.id.VPIDEntityKey internalVpid = CommonEntityKeyFactory.createVPIDEntityKey(finder.getFinderData());

			AbstractEntityFinder personFinder = (AbstractEntityFinder) finder;

			if(operationName != null && !"".equals(operationName) && operationName.equalsIgnoreCase("eeSummary") && (personFinder.getRequestName().equalsIgnoreCase("IVMDATA")) || personFinder.getRequestName().equalsIgnoreCase("FtPDAta"))
				{
				 //person = getPersonService().getPerson(internalVpid);

				//CCR12665-EE Summary performance issue should be fixed by this code change.
				 //This changes include sites info for a patient that now will be provided by a 1305 composite call.
				 person = getPersonService().getPersonWithCompositeCall(internalVpid);
				}
			else
				{
				person = getPersonService().getPersonWithoutIdentityTraits(internalVpid);
				}

		} else {
			// search mode
			PersonSearchQueryInfo searchQueryInfo = new PersonSearchQueryInfo();
			if (finder instanceof SSNEntityFinder) {
				searchQueryInfo.setUnformattedSsn(finder.getFinderData());
			} else if (finder instanceof LNSEntityFinder) {
				/*
				 * TODO: talk to PSIM on how to support this commonly used
				 * legacy approach
				 */
				throw new ESRException("LNS person finder not yet implemented");
			}

			List persons = getPersonService().search(searchQueryInfo, true,
					false, false, -1);

			if (persons == null || persons.size() <= 0) {
				return null;
			}

			if (persons.size() > 1) {
				throw new ESRException(
						"More than one person found with provided input");
			}
			person = (Person) persons.get(0);
		}
		return person;
	}


	public gov.va.med.esr.service.PersonService getPersonService() {
		// return personService;

		if (personService == null) {
			personService = (gov.va.med.esr.service.PersonService) getBeanFactory()
					.getBean("personService");
		}
		return personService;

	}

	public void setPersonService(
			gov.va.med.esr.service.PersonService personService) {
		this.personService = personService;
	}

	public ExternalSummaryFactory getExternalSummaryFactory() {

		if (externalSummaryFactory == null) {
			externalSummaryFactory = (ExternalSummaryFactory) getBeanFactory()
					.getBean("externalSummaryFactory");
		}
		return externalSummaryFactory;
	}

	public void setExternalSummaryFactory(
			ExternalSummaryFactory externalSummaryFactory) {
		this.externalSummaryFactory = externalSummaryFactory;
	}

	public ExternalHandBookFactory getExternalHandBookFactory() {

		if (externalHandBookFactory == null) {
			externalHandBookFactory = (ExternalHandBookFactory) getBeanFactory()
					.getBean("externalHandBookFactory");
		}
		return externalHandBookFactory;
	}

	public void setExternalHandBookFactory(
			ExternalHandBookFactory externalHandBookFactory) {
		this.externalHandBookFactory = externalHandBookFactory;
	}
/*
    public ClinicalDeterminationService getClinicalDeterminationService() {
        return clinicalDeterminationService;
    }
*/
    public void setClinicalDeterminationService(
            ClinicalDeterminationService clinicalDeterminationService) {
        this.clinicalDeterminationService = clinicalDeterminationService;
    }
/*
    public DemographicService getDemographicService() {
        return demographicService;
    }
*/
    public void setDemographicService(DemographicService demographicService) {
        this.demographicService = demographicService;
    }


    private boolean isValidforPrimaryviewUpdate(Person person){
    	boolean valid = false;
    	if(person != null){
    		if( (person.getDeathRecord()== null ||
    				 person.getDeathRecord().getDeathDate() == null ||
    				  person.getDeathRecord().getDeathDate().getDate() == null    //CCR11536 - precise date yyyyMMdd
    			)
    			&& person.getEnrollmentDetermination() != null){
    			valid = true;
    		}
    	}
    	return valid;
    }

	public HandBookService getHandBookService() {
		if (handBookService == null) {
			handBookService = (HandBookService) getBeanFactory()
					.getBean("handBookService");
		}
		return handBookService;
	}

	public void setHandBookService(HandBookService handBookService) {
		this.handBookService = handBookService;
	}

	public CommsEmailBulletinService getCommsEmailBulletinService() {
		if (commsEmailBulletinService == null) {
			commsEmailBulletinService = (CommsEmailBulletinService) getBeanFactory()
					.getBean("commsEmailBulletinService");
		}
		return commsEmailBulletinService;
	}

	public void setCommsEmailBulletinService(
			CommsEmailBulletinService commsEmailBulletinService) {
		this.commsEmailBulletinService = commsEmailBulletinService;
	}
	private void sendEmail(DeliveryPreferenceInfo info, DeliveryPreference dp) throws ServiceException
	   {
		   if (info.getDeliveryPreference() != null && dp.getDeliveryPreferenceType() != null &&
				   !info.getDeliveryPreference().equalsIgnoreCase(dp.getDeliveryPreferenceType().getName()))
		   {
			   if (dp.getDeliveryPreferenceType().getCode().equals("2") &&
					   info.getDeliveryPreference().equalsIgnoreCase("MAIL") )
			   {  //change from mail to online
				     if(info.getEmailAddress() != null){
					   getCommsEmailBulletinService().sendEmailBulletin(
							   BulletinTrigger.DataType.DELIVERY_PREFERENCE_CHANGE_MAIL_TO_ONLINE,
							   info.getEmailAddress());
				     }

			   } else if (dp.getDeliveryPreferenceType().getCode().equals("1") &&
					   info.getDeliveryPreference().equalsIgnoreCase("ONLINE"))
			   {
				   //change from online to mail
				   if(info.getEmailAddress() != null){
				   		getCommsEmailBulletinService().sendEmailBulletin(
				   				BulletinTrigger.DataType.DELIVERY_PREFERENCE_CHANGE_ONLINE_TO_MAIL,
				   				info.getEmailAddress());
				   }
			   }
		   }

	   }

	private String getICN(List correlations)
    {
    	if (correlations == null || correlations.size() == 0)
    		return null;

    	PatientIdentifier pid = null;

		Iterator it = correlations.iterator();
		while (it.hasNext())
		{
			pid = (PatientIdentifier)it.next();
			if ("200M".equals(pid.getStationNumber()))
				return pid.getIdentity();
		}

		return null;
    }

	public IdmWebServiceDelegate getIdmServiceDelegate() {
		if (idmServiceDelegate == null) {
			idmServiceDelegate = (IdmWebServiceDelegate) getBeanFactory()
					.getBean("idmServiceDelegate");
		}
		return idmServiceDelegate;
	}

	public void setIdmServiceDelegate(IdmWebServiceDelegate idmServiceDelegate) {
		this.idmServiceDelegate = idmServiceDelegate;
	}

	public LookupService getLookupService() {
		if (lookupService == null) {
			lookupService = (LookupService) getBeanFactory()
					.getBean("lookupService");
		}
        return lookupService;
    }
}
