/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.persistent.history;

import java.math.BigDecimal;
import java.lang.Float;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Filter;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;

import gov.va.med.esr.common.model.ee.EnrollmentDetermination;
import gov.va.med.esr.common.model.lookup.EnrollmentPriorityGroup;
import gov.va.med.esr.common.model.lookup.EnrollmentStatus;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.service.impl.ChangeEvent;
import gov.va.med.fw.model.AbstractVersionedEntity;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.persistent.hibernate.AbstractDAOAction;
import gov.va.med.esr.service.EEResultInfo;

// Common Classes

/**
 * 
 * @author DNS   CHENJ2
 * 
 */
public class RulesEnrollmentHistoryDAOImpl extends HistoryDAOImpl
	implements RulesEnrollmentHistoryDAO {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -2356344899457437651L;

	private static final String FILTER_EFF_DATE_ASOF = "incomeTestEffDateAsOfFilter";

	private static final String FILTER_EFF_DATE_PRIOR = "incomeTestEffDatePriorToFilter";

	private static final String FILTER_PAR_EFF_DATE = "effectiveDate";

	private static final String INCOME_TEST_PROP_PATH = "internalIncomeTests";

	private static final String INCOME_TEST_STATUS_PROP_PATH = "internalIncomeTests.internalStatuses";

	private static final String getPreviousEnrollment_Date_Query = "enrollmentHistoryQuery_GetDateForPrevious";

	private static final String getMostRecentWStatus_Date_Query= "enrollmentHistoryQuery_GetDateForMostRecentWStatus";

	private static final String getApplicationDate_Query = "enrollmentHistoryQuery_GetApplicationDate";

	private static final String getFirstNotNullEffDate_Query = "enrollmentHistoryQuery_GetFirstNotNullEffDate";

	private static final String getEnDtForEarliestAfter_Query = "enrollmentHistoryQuery_GetEnDtForEarliestEnrollmentAfter";
	
	private static final String getEffectiveDateForEarliestAfter_Query = "enrollmentHistoryQuery_GetEffectiveDateForEarliestEnrollmentAfter";

	private static final String getPrGrpForEarliestAfter_Query = "enrollmentHistoryQuery_GetPrGrpForEarliestEnrollmentAfter";
	
	private static final String getPrGrpForEarliestWStatus_Query = "enrollmentHistoryQuery_GetPrGrpForEarliestWStatus";

	private static final String getEnDtForEarliestWStatus_Query = "enrollmentHistoryQuery_GetEnDtForEarliestWStatus";
	
	private static final String getEffectiveDateForEarliestWStatus_Query = "enrollmentHistoryQuery_GetEffectiveDateForEarliestWStatus";

    private static final String getAppDtForEarliestAfter_Query = "enrollmentHistoryQuery_GetAppDtForEarliestEnrollmentAfter";

    private static final String getAppDtForEarliestWStatus_Query = "enrollmentHistoryQuery_GetAppDtForEarliestWStatus";    

	private static final String getStatusForEarliest_Query = "batchProcessQuery_GetStatusForEarliest";
	
	private static final String getPriorityGrpsForMostRecent_Query = "batchProcessQuery_GetPriorityGrpsForMostRecent";
	// CR 9803 and CCR 10023
	private static final String getMostRecentVerifiedEnrollPriorityGrps_Query = "enrollmentHistoryQuery_MostRecentVerifiedEnrollPriorityGrps";

	private static final String getMostRecentNonNullPriority_Query = "enrollmentHistoryQuery_GetMostRecentNonNullPriority";  
    private static final String getMostRecentNonNullPriorityLevelByDate_Query = "enrollmentHistoryQuery_GetMostRecentNonNullPriorityLevelByDate"; 
    
    private static final String getPriorityGrpsBeforePH_Query = "enrollmentHistoryQuery_GetPriorityGrpsBeforePH";
    
    private static final String getPersonEnrollHistory_Query = "enrollmentHistoryQuery_GetPersonHistory";
    
    private static final String getPriorToEnrollHistory_Query = "enrollmentHistoryQuery_PriorToDate";


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

	/*
	 * Retrieves the current or previous version of the entity
	 * 
	 * @param changeEvent provides the key to the root object, and timestamp for
	 * history retrieval
	 * 
	 */
	protected AbstractVersionedEntity getHistoricalEntity(Session session, 
			ChangeEvent changeEvent) throws DAOException {

		// use the regular time filter + filter on effective date on the main
		// income test. For the child (IncomeTestStatus, it doesn't populate the
		// effective date, so we cannot run the same filters on the child.) use
		// the modifiedOn filter

		Person p = null;

		try {

			p = (Person) super.getHistoricalEntity(session, changeEvent);

			if (p != null) {

				String effDateFilterName = getEffDateFilterName(session);
				if (effDateFilterName != null) {
					// apply effective date filter, and access income tests
					session.enableFilter(effDateFilterName).setParameter(
							FILTER_PAR_EFF_DATE, changeEvent.getTimeStamp());
					processNestedProperty(p, INCOME_TEST_PROP_PATH, ACCESS_ONLY);
					session.disableFilter(effDateFilterName);

					// do not use effective date filter, and get income test
					// status, using the regular filters (this does not have the
					// eff date
					// column populated

					processNestedProperty(p, INCOME_TEST_STATUS_PROP_PATH,
							ACCESS_ONLY);
				}
			}
		} catch (Exception e) {
			throw new DAOException(
					"Failed to get Historical Entity for changeEvent: "
							+ changeEvent, e);
		}

		return p;
	}

	private String getEffDateFilterName(Session session) {
		Filter f = session.getEnabledFilter(FILTER_AS_OF_DATE);
		if (f != null) {
			return FILTER_EFF_DATE_ASOF;
		}

		// else
		f = session.getEnabledFilter(FILTER_PRIOR_TO_DATE);
		if (f != null) {
			return FILTER_EFF_DATE_PRIOR;
		}

		// else
		return null;
	}

	protected void removeDeletedRecords(AbstractVersionedEntity entity)
			throws DAOException {

		super.removeDeletedRecords(entity);

		processNestedProperty(entity, INCOME_TEST_PROP_PATH, ACCESS_AND_DELETE);
		processNestedProperty(entity, INCOME_TEST_STATUS_PROP_PATH,
				ACCESS_AND_DELETE);
	}

	/**
	 * In this particular case, we don't need to retrieve the previous version
	 * 
	 * @return
	 */
	protected boolean needPreviousVersion() {
		return false;
	}

	/*
	 * 
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#getPersonForPriorEnrollment(gov.va.med.fw.model.EntityKey)
	 */
	public Person getPersonForPriorEnrollment(EntityKey personId)
			throws DAOException {
		Person p = null;

		ChangeEvent changeEvent = getHistoryChangeEventForQuery(getPreviousEnrollment_Date_Query, personId, null);
		
		/* See below this won't really work anyways...
		//EnrollmentDetermination e = getEnrollmentForQuery(getPreviousEnrollment_Query, personId);
		//if (e != null) {
			
			// enrollment has a proxy reference to person, this interferes with the person 
			// directly retrieved out.  So let's carefully remove the reference to the proxy.
			evict(e.getPerson());
			e.setPerson(null);
			
			ChangeEvent changeEvent = new ChangeEvent(new Timestamp(e.getModifiedOn().getTime()), personId);
		*/	
		if (changeEvent != null) {
			// get person
			Map contextData = new HashMap();
			contextData.put("changeEvent", changeEvent);				        		        	
			HibernateCallback callback = new AbstractDAOAction(contextData) { 
				public Object execute(Session session) throws DAOException {
					return getCurrentVersion(session, (ChangeEvent) getContextData().get("changeEvent"));
				}
			};
			
			p = (Person) this.getHibernateTemplate().execute(callback);
			
			/*
			 * The following didn't quite work, since p.setEnrollment would trigger
			 * getInternalEnrollments, which performs the lazy instantiation...  So
			 * we won't be optimizing getting enrollment first and attaching to person
			 * 
			// we have to reattach person to session, otherwise we'd
			// cause a lazy-instantiation error.
			getSession().lock(p, LockMode.NONE);
			p.setEnrollmentDetermination(e);
			// now detach everthing from the root
			evict(p);*/
		}
		return p;
	}

    
    
	/**
     * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#getMostRecentNonNullPriorityCode(gov.va.med.fw.model.EntityKey)
     */
    public String getMostRecentNonNullPriorityCode(EntityKey personId) throws DAOException {
        Map contextData = new HashMap();
        contextData.put("personId", personId);                                          
        HibernateCallback callback = new AbstractDAOAction(contextData) { 
            public Object execute(Session session) {
                Query q = session.getNamedQuery(getMostRecentNonNullPriority_Query);
                q.setMaxResults(1);
                q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());

                return q.list();                
            }
        };
        
        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
            
        String enrollmentPriorityGroupCode = iter.hasNext() ? (String) iter.next() : null;
        return enrollmentPriorityGroupCode;
    }

    public String getMostRecentNonNullPriorityLevelByDate(EntityKey personId, final Date beforeDate) throws DAOException {
        Map contextData = new HashMap();
        contextData.put("personId", personId);                                          
        HibernateCallback callback = new AbstractDAOAction(contextData) { 
            public Object execute(Session session) {
                Query q = session.getNamedQuery(getMostRecentNonNullPriorityLevelByDate_Query);
                q.setMaxResults(1);
                q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
                q.setParameter("beforeDate", beforeDate);

                return q.list();                
            }
        };
        
        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
            
        String enrollmentPriorityGroupCode = iter.hasNext() ? (String) iter.next() : null;
        return enrollmentPriorityGroupCode;
    }
    
    /*
	 * 
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#getAppDateForMostRecentUnverifiedEnrollment(gov.va.med.fw.model.EntityKey)
	 */
	public Date getAppDateForMostRecentUnverifiedEnrollment(EntityKey personId)
			throws DAOException {
		
		Date applicationDate = null;
		
		// first get enrollment history timestamp
		ChangeEvent changeEvent = getHistoryChangeEventForQuery(getMostRecentWStatus_Date_Query, personId, EnrollmentStatus.CODE_UNVERIFIED.getCode());
		
		if (changeEvent != null) {
			applicationDate = getApplicationDate(changeEvent);
		}
		// next get application date
		return applicationDate;
	}

	/**
	 * Execute query to get a person's application date based on modifiedOn timestamp
	 * @param modifiedDate
	 * @param personId
	 * @return
	 */
	private Date getApplicationDate(ChangeEvent ce) {
		Date applicationDate = null;
		
		Map contextData = new HashMap();
		contextData.put("ce", ce);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) {
				ChangeEvent targetChangeEvent = (ChangeEvent) getContextData().get("ce");
				
				Query q = session.getNamedQuery(getApplicationDate_Query);
				q.setMaxResults(1);
				q.setParameter("personId", targetChangeEvent.getEntityKey().getKeyValue());
				q.setParameter("historyDate", targetChangeEvent.getTimeStamp());
				return q.list();
			}
		};
		List results = this.getHibernateTemplate().executeFind(callback);
		Iterator iter = results.iterator();
		applicationDate = iter.hasNext() ? (Date) iter.next() : null;
		
		return applicationDate;
	}
	
	/*
	 * 
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#getFirstNotNullEffDate(gov.va.med.fw.model.EntityKey)
	 */
	public Date getFirstNotNullEffDate(EntityKey personId)
			throws DAOException {
		
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) {
				Query q = session.getNamedQuery(getFirstNotNullEffDate_Query);
				q.setMaxResults(1);
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};
		List results = this.getHibernateTemplate().executeFind(callback);
		Iterator iter = results.iterator();
		
		Date effDate = iter.hasNext() ? (Date) iter.next() : null;
		return effDate;
	}

/*
 *  This approach doesn't work really well, since person would end up fetching enrollment
 *  anyways.  (If you fetch enrollment ahead of time and try to link it to person, the
 *  setEnrollment call would do getInternalEnrollments first, which triggers the lazy instantiation
 *  of enrollment from database...
 *  
 * 	private EnrollmentDetermination getEnrollmentForQuery(String queryName, EntityKey personId
			) throws DAOException {

		Query q = getSession().getNamedQuery(queryName);
		q.setMaxResults(1);
		q.setParameter("personId", (BigDecimal) personId.getKeyValue());
		Iterator iter = q.list().iterator();
		
		EnrollmentDetermination e = iter.hasNext() ? (EnrollmentDetermination) iter.next() : null;
		return e;
	}

 */
	/**
	 * Get the modifiedOn timestamp for the enrollment record that matches this query
	 * Set to public for query performance testing
	 */
	private ChangeEvent getHistoryChangeEventForQuery(String queryName, EntityKey personId, String enrollmentStatus
			) throws DAOException {

		ChangeEvent changeEvent = null;

		Map contextData = new HashMap();
		contextData.put("queryName", queryName);				        		        	
		contextData.put("personId", personId);
		contextData.put("enrollmentStatus", enrollmentStatus);
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) {
				Query q = session.getNamedQuery((String) getContextData().get("queryName"));
				q.setMaxResults(1);
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				String targetEnrollmentStatus = (String) getContextData().get("enrollmentStatus");
				if (targetEnrollmentStatus != null) {
					q.setParameter("status", targetEnrollmentStatus);
				}
				return q.list();				
			}			
		};
		List results = this.getHibernateTemplate().executeFind(callback);
		Iterator iter = results.iterator();
		
		Timestamp modifiedDate = iter.hasNext() ? (Timestamp) iter.next() : null;
		if (modifiedDate != null) {
			changeEvent = new ChangeEvent(modifiedDate, personId);
		}
		return changeEvent;
	}

	/*
	 * 
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#getStatusAndAppDateForEarliest(gov.va.med.fw.model.EntityKey)
	 */
	public Object[] getStatusAndAppDateForEarliest(EntityKey personId)
	throws DAOException {
		Object[] results = null;
		
		// first get the status and modifiedOn timestamp for the earliest enrollment
		Map contextData = new HashMap();				        		        	
		contextData.put("personId", personId);
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) {
				Query q = session.getNamedQuery(getStatusForEarliest_Query);
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};
		List resultsFromQuery = this.getHibernateTemplate().executeFind(callback);
		Iterator iter = resultsFromQuery.iterator();

		if (iter.hasNext()) {
			Timestamp modifiedDate = null;
			EnrollmentStatus status = null;
			Date applicationDate = null;

			Object[] row = (Object[])iter.next();
			status = (EnrollmentStatus) row[0];
			modifiedDate = (Timestamp) row[1];
		
			// then get the matching application date
			if (modifiedDate != null) {
				applicationDate = getApplicationDate(new ChangeEvent(modifiedDate, personId));
			}
			
			results = new Object[]{status, applicationDate};
		}
		
		return results;
	}
	
	/*
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#getPriorityGrpsForMostRecent(gov.va.med.fw.model.EntityKey)
	 */
	public String[] getPriorityGrpsForMostRecent(EntityKey personId)
	throws DAOException {
		Object[] results = null;
		String[] priorityGrps = null;
		
		Iterator iter = findByNamedQueryAndNamedParam(
				getPriorityGrpsForMostRecent_Query,
				"personId", (BigDecimal) personId.getKeyValue())
				.iterator();		

		if (iter.hasNext()) {
			results = (Object[])iter.next(); 
			priorityGrps = new String[] {(String)results[0], (String)results[1]};
		}
		return priorityGrps;
	}
	
	/**
	 * Returns the Enrollment Date from the earliest enrollment with Verified Status
	 * UNLESS a Cancel Decline Status is encountered, in which case use
	 * subsequent (one more recent than cancel). 
	 * 
	 * UC requirements: All previous enrollment records are examined to determine the Enrollment Date to apply
	 * to the new record. Use the Enrollment from the earliest enrollment record
	 * found that has an Enrollment Status of Verified, unless a
	 * Cancelled/Declined record is encountered. In that case, use the
	 * Enrollment Date from the earliest record subsequent to the
	 * Cancelled/Declined record. If there was not a previous Verified Record
	 * then the Enrollment Date is today’s date.
	 * 
	 * @param personId
	 * @return
	 */
	public Date getEnrollmentDateForEarliestVerifiedUnlessCancelled(EntityKey personId)
	throws DAOException
	{
		Date enrollmentDate = null;

		// find latest enrollment with status="cancel decline"
		Date cancelDeclineDate = getDateForMostRecentCancelDeclineEnrollment(personId);
		if (cancelDeclineDate != null) {
			// if found: find verified enrollment immediately after it (if that's not found return today's date)
			enrollmentDate = getEnrollmentDateForVerifiedEnrollmentAfter(personId, cancelDeclineDate);
			if (enrollmentDate == null) {
				enrollmentDate = new Date();
			}
		}
		else {
			// else: find earliest verified enrollment (if not found, return today's date)
			enrollmentDate = getEnrollmentDateForEarliestVerifiedEnrollment(personId);
			if (enrollmentDate == null) {
				enrollmentDate = new Date();
			}
		}
		return enrollmentDate;
	}

    
    /**
     * Returns the Effective Date from the earliest enrollment with Verified Status
     * UNLESS a Cancel Decline or Rejected Below Threshold status is encountered, in which case use
     * subsequent (one more recent than cancel). 
     * 
     * @param personId
     * @return
     */
    public Date getEffectiveDateForEarliestVerifiedUnlessCancelledOrRejectedBelowEnrollmentThreshold(EntityKey personId)
    throws DAOException
    {
        Date effectiveDate = null;

        // find latest enrollment with status="cancel decline"
        Date cancelDeclineDate = getDateForMostRecentCancelDeclineEnrollment(personId);
        Date rejectedDate = getDateForMostRecentRejectedBelowThresholdEnrollment(personId);
        Date latestDate = null;
        if (cancelDeclineDate == null && rejectedDate == null) {
            latestDate = null;
        } else if (cancelDeclineDate != null && rejectedDate == null) {
            latestDate = cancelDeclineDate;
        } else if (cancelDeclineDate == null && rejectedDate != null) {
            latestDate = rejectedDate;
        } else if (cancelDeclineDate.before(rejectedDate)) {
            latestDate = rejectedDate;
        } else {
            latestDate = cancelDeclineDate;
        }
        if (latestDate != null) {
            // if found: find verified enrollment immediately after it
            effectiveDate = getEffectiveDateForVerifiedEnrollmentAfter(personId, latestDate);
        }
        else {
            // else: find earliest verified enrollment
            effectiveDate = getEffectiveDateForEarliestVerifiedEnrollment(personId);
        }
        return effectiveDate;
    }
    
    /**
     * Enrollment Application Date – All previous enrollment records are
     * examined to determine the Enrollment Application Date to apply to the new
     * record. Use the Application Date from the earliest enrollment record
     * found that has an Enrollment Status of Unverified, unless one with the
     * status of Cancelled/Declined or Rejected; Below Enrollment Group
     * Threshold is encountered. In that case, use the Application Date from the
     * earliest Unverified record subsequent to the Cancelled/Declined or
     * Rejected; Below Enrollment Group Threshold record. If no previous
     * Application Date is found leave the Application Date null. A null value
     * should never overlay a true date in the current record.
     * 
     * 
     * @param personId
     * @return
     */
	public Date getEnrollmentApplicationDateForEarliestSpecifiedStatusUnlessCancelledOrRejectedBelowThreshold(EntityKey personId)
	throws DAOException {
	    Date applicationDate = null;

	    // find latest enrollment with status="cancel decline"
        Date cancelDeclineDate = getDateForMostRecentCancelDeclineEnrollment(personId);
        Date rejectedDate = getDateForMostRecentRejectedBelowThresholdEnrollment(personId);
        Date latestDate = null;
        if (cancelDeclineDate == null && rejectedDate == null) {
            latestDate = null;
        } else if (cancelDeclineDate != null && rejectedDate == null) {
            latestDate = cancelDeclineDate;
        } else if (cancelDeclineDate == null && rejectedDate != null) {
            latestDate = rejectedDate;
        } else if (cancelDeclineDate.before(rejectedDate)) {
            latestDate = rejectedDate;
        } else {
            latestDate = cancelDeclineDate;
        }
	    if (latestDate != null) {
	        // if cancel found, find enrollment with specified status immediately after its date
            applicationDate = this.getEnrollmentApplicationDateForSpecifiedStatusAfter(personId,
                    latestDate, EnrollmentStatus.CODE_UNVERIFIED.getCode());
            if (applicationDate == null) {
                applicationDate = this.getEnrollmentApplicationDateForSpecifiedStatusAfter(personId,
                        latestDate, EnrollmentStatus.CODE_PENDING_ELIGIBILITY_STATUS_IS_UNVERIFIED.getCode());                
            }
	    }
	    else {
	        // else: find earliest enrollment with specified status
            applicationDate = getEnrollmentApplicationDateForSpecifiedStatus(personId, 
                    EnrollmentStatus.CODE_UNVERIFIED.getCode());
            if (applicationDate == null) {
                applicationDate = getEnrollmentApplicationDateForSpecifiedStatus(personId, 
                        EnrollmentStatus.CODE_PENDING_ELIGIBILITY_STATUS_IS_UNVERIFIED.getCode());
            }
	    }
	    return applicationDate;
	}    
	
	/**
	 * P8 Method: Get the Priority Group for the Earliest Verified Unless Cancelled Enrollment Determination record.
	 * @param personId
	 * @return
	 * @throws DAOException
	 */
	
	public EnrollmentDetermination getEnrollmentDeterminationForEarliestVerifiedUnlessCancelledOrRejectedBelowEnrollmentGroupThreshold(EntityKey personId)
	throws DAOException
	{
		String priorityGroupCode="";
		Date enrollmentDate = null;
		EnrollmentDetermination enrollmentDetermination=null;

		// find latest enrollment with status="cancel decline" or rejected
        Date cancelDeclineDate = getDateForMostRecentCancelDeclineEnrollment(personId);
        Date rejectedDate = getDateForMostRecentRejectedBelowThresholdEnrollment(personId);
        Date latestDate = null;
        if (cancelDeclineDate == null && rejectedDate == null) {
            latestDate = null;
        } else if (cancelDeclineDate != null && rejectedDate == null) {
            latestDate = cancelDeclineDate;
        } else if (cancelDeclineDate == null && rejectedDate != null) {
            latestDate = rejectedDate;
        } else if (cancelDeclineDate.before(rejectedDate)) {
            latestDate = rejectedDate;
        } else {
            latestDate = cancelDeclineDate;
        }
        
		if (latestDate != null) {
			// if found: find verified enrollment immediately after it (if that's not found return today's date)
			enrollmentDetermination = getPriorityGroupForVerifiedEnrollmentAfter(personId, latestDate);
			
			if (enrollmentDate == null) {
				enrollmentDate = new Date();
			}
		}
		else {
			// else: find earliest verified enrollment (if not found, return today's date)
			enrollmentDetermination = getPriorityGroupForEarliestVerifiedEnrollment(personId);
		}
		return enrollmentDetermination;
	}
	
	/* (non-Javadoc)
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#getEarliestEnrollmentEffectiveDatewithAOWatDMZ(gov.va.med.fw.model.EntityKey)
	 */
	public Date getEarliestEnrollmentEffectiveDatewithAOWatDMZ(EntityKey personId) throws DAOException {
		// execute the named query
		Map contextData = new HashMap();				        		        	
		contextData.put("personId", personId);
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_verifiedEnrollmentForAOE");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};
		List results = this.getHibernateTemplate().executeFind(callback);
		Iterator iter = results.iterator();
		Date enrollmentEffectiveDate = null;
		
		//Fetch the data of results are returned
        if (iter.hasNext()) {
            Object row = iter.next();
            if (row != null) {
                enrollmentEffectiveDate = (Timestamp) row;
            }
        }
		//return the enrollment effective date
		return enrollmentEffectiveDate;
	}

	/* (non-Javadoc)
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#isApplicationDatePriortoEGTEffectiveDate(gov.va.med.fw.model.EntityKey)
	 */
	public boolean isApplicationDatePriortoEGTEffectiveDate(EntityKey personId) throws DAOException {
		boolean exists = false;
		// execute the named query
		Map contextData = new HashMap();				        		        	
		contextData.put("personId", personId);
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_appDatePriorToEGTDate");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();
			}
		};
		List results = this.getHibernateTemplate().executeFind(callback);
		Iterator iter = results.iterator();
				
		//Fetch the data of results are returned
		if (iter.hasNext()) {
			exists = true;
		}
		return exists;
	}

	/* (non-Javadoc)
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#isVerifiedEnrollmentExistsforCombatVeteran(gov.va.med.fw.model.EntityKey)
	 */
	public boolean isVerifiedEnrollmentExistsforCombatVeteran(EntityKey personId) throws DAOException {
		boolean exists = false;
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_verifiedEnrollmentForCombatVeteran");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
				
		//Fetch the data of results are returned
		if (iter.hasNext()) {
			exists = true;
		}
		return exists;
	}

	/* (non-Javadoc)
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#isVerifiedEnrollmentExistsForEligibilityCode(gov.va.med.fw.model.EntityKey, java.lang.String)
	 */
	public boolean isVerifiedEnrollmentExistsForEligibilityCode(EntityKey personId, String eligiblityTypeCode) throws DAOException {
		boolean exists = false;
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		contextData.put("eligiblityTypeCode", eligiblityTypeCode);
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_verifiedEnrollmentEligCode");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				q.setParameter("eligibilityTypeCode", getContextData().get("eligiblityTypeCode"));
				return q.list();				
			}
		};
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
				
		//Fetch the data of results are returned
		if (iter.hasNext()) {
			exists = true;
		}
		return exists;
	}


    public Integer getIncomeYearForVerifiedMT(EntityKey personId) throws DAOException {
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_GetIncomeYearForVerifiedIncomeTest");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};

        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
        Integer incomeYear = null;
        
        //Fetch the data of results are returned
        if (iter.hasNext()) {
            Object row = iter.next();
            if (row != null) {
                incomeYear = (Integer) row;
            }
        }

        return incomeYear;        
	}
    
    public List getIncomeYearsForVerifiedMT(EntityKey personId) throws DAOException {
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_GetMultiIncomeYearsForVerifiedIncomeTest");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};

        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
        Integer incomeYear = null;
        ArrayList incomeYears = new ArrayList();
        
        // CR 9803 and CCR 10023 needed this change to be able to work
        //Fetch the data of results are returned
        while (iter.hasNext()) {
            Object row = iter.next();
            if (row != null) {
                incomeYear = (Integer) row;
                incomeYears.add(incomeYear);
            }
        }

        return incomeYears;        
	}

    // CodeCR10023 and CR9803
	public List getIncomeYearsForVerifiedP8(EntityKey personId) throws DAOException {
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_GetMultiIncomeYearsForVerifiedP8");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};

        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
        Integer incomeYear = null;
        ArrayList incomeYears = new ArrayList();
        
        //Fetch the data of results are returned
        while (iter.hasNext()) {
            Object row = iter.next();
            if (row != null) {
                incomeYear = (Integer) row;
                incomeYears.add(incomeYear);
            }
        }

        return incomeYears;
	}    
    
	
	// CodeCR10023 and CR9803	
	public String[] getMostRecentVerifiedEnrollmentPriorityGroups(EntityKey personId) throws DAOException {
		Object[] results = null;
		String[] priorityGrps = null;
		
		Iterator iter = findByNamedQueryAndNamedParam(
				getMostRecentVerifiedEnrollPriorityGrps_Query,
				"personId", (BigDecimal) personId.getKeyValue()).iterator();		

		if (iter.hasNext()) {
			results = (Object[])iter.next(); 
			priorityGrps = new String[] {(String)results[0], (String)results[1]};
		}
		return priorityGrps;
	}
	// CodeCR10023 and CR9803
	public boolean hasIncomeTestMeetingP8RecheckCriteria(EntityKey personId, float relaxPercent) throws DAOException {
		boolean exists = false;
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);
		contextData.put("relaxPercent", new Float(relaxPercent));
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_hasIncomeTestMeetingP8RecheckCriteria");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				q.setFloat("relaxPercent", ((Float)getContextData().get("relaxPercent")).floatValue());				
				return q.list();				
			}
		};
		
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
				
		//Fetch the data of results are returned
		if (iter.hasNext()) {
			exists = true;
		}
		return exists;
	}

	// CodeCR10023 and CR9803	
	   public List getHistoricalIncomeYearsForVerifiedMT(EntityKey personId) throws DAOException  {

		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_GetHistoricalMultiIncomeYearsForVerifiedIncomeTest");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};

        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
        Integer incomeYear = null;
        ArrayList incomeYears = new ArrayList();
        
        // CR 9803 and CCR 10023 needed this change to be able to work
        //Fetch the data of results are returned
        while (iter.hasNext()) {
            Object row = iter.next();
            if (row != null) {
                incomeYear = (Integer) row;
                incomeYears.add(incomeYear);
            }
        }

        return incomeYears;        
	}

	/* (non-Javadoc)
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#isVerifiedEnrollmentExistsforSvcConnPercent(gov.va.med.fw.model.EntityKey, java.lang.Integer)
	 */
	public boolean isVerifiedEnrollmentExistsforSvcConnPercent(EntityKey personId, Integer percent) throws DAOException {
		boolean exists = false;
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		contextData.put("percent", percent);
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_verifiedEnrollmentForSCAWP10");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
				
		//Fetch the data of results are returned
		if (iter.hasNext()) {
			exists = true;
		}
		return exists;
	}

    /**
     * Returns true if any enrollment exists for person before the specified date
     * @param personId
     * @return
     * @throws DAOException
     */
    public boolean hasAnyEnrollmentRecordBeforeDate(EntityKey personId, Date beforeDate) throws DAOException {
        boolean exists = false;
        // execute the named query
        Map contextData = new HashMap();
        contextData.put("personId", personId);
        contextData.put("dateParam", beforeDate);  
        HibernateCallback callback = new AbstractDAOAction(contextData) { 
            public Object execute(Session session) {
                Query q = session.getNamedQuery("contEnrollment_anyEnrollmentBefore");
                q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
                q.setParameter("dateParam", getContextData().get("dateParam"));
                return q.list();                
            }
        };
        
        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
                
        //Fetch the data of results are returned
        if (iter.hasNext()) {
            exists = true;
        }
        
        return exists;
    }
    
	/**
	 * Returns true if a verified Enrollment exists for person
	 * @param personId
	 * @return
	 * @throws DAOException
	 */
	public boolean isVerifiedEnrollmentExists(EntityKey personId) throws DAOException {
		boolean exists = false;
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_verifiedEnrollment");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};
		
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
				
		//Fetch the data of results are returned
		if (iter.hasNext()) {
			exists = true;
		}
		return exists;
	}

    
    
	public EEResultInfo getMostRecentEnrollmentforContinuousEnrollment(EntityKey personId) throws DAOException {
        //get timestamp for the most recent enrollment
        // execute the named query
        Map contextData = new HashMap();
        contextData.put("personId", personId);                                          
        HibernateCallback callback = new AbstractDAOAction(contextData) { 
            public Object execute(Session session) {
                Query q = session.getNamedQuery("contEnrollment_recentEnrollmentDataForCE");
                q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
                return q.list();                                
            }
        };
        
        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
        
        if (iter.hasNext()) {
            EEResultInfo results = new EEResultInfo();
            Object[] row = (Object[])iter.next();
            results.setEffectiveDate((Timestamp) row[0]);
            results.setOverrideFlag((Integer) row[1]);            
            results.setGroupCode((String) row[2]);
            results.setStatusCode((String) row[3]);            
            return results;
        }
        return null;
    }


	private Date getDateForMostRecentCancelDeclineEnrollment(EntityKey personId) throws DAOException
	{
		ChangeEvent changeEvent = getHistoryChangeEventForQuery(getMostRecentWStatus_Date_Query, personId, EnrollmentStatus.CODE_CANCELLED_DECLINED.getCode());
		return (changeEvent == null? null: changeEvent.getTimeStamp());
	}	  
	
    private Date getDateForMostRecentRejectedBelowThresholdEnrollment(EntityKey personId) throws DAOException
    {
        ChangeEvent changeEvent = getHistoryChangeEventForQuery(getMostRecentWStatus_Date_Query, personId, EnrollmentStatus.CODE_REJECTED_BELOW_ENROLLMENT_GROUP_THRESHOLD.getCode());
        return (changeEvent == null? null: changeEvent.getTimeStamp());
    }   

	 /**
     * Get effective date for the enrollment immediately following the date for
     * the cancel decline record.
     * 
     * @param cancelDeclineDate
     * @return
     */
    private Date getEffectiveDateForVerifiedEnrollmentAfter(EntityKey personId, Date cancelDeclineDate) 
    {
        Map contextData = new HashMap();
        contextData.put("personId", personId);                                          
        contextData.put("cancelDeclineDate", cancelDeclineDate);
        HibernateCallback callback = new AbstractDAOAction(contextData) { 
            public Object execute(Session session) {
                Query q = session.getNamedQuery(getEffectiveDateForEarliestAfter_Query);
                q.setMaxResults(1);
                q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
                q.setParameter("status", EnrollmentStatus.CODE_VERIFIED.getCode());
                q.setParameter("dateParam", getContextData().get("cancelDeclineDate"));

                return q.list();                
            }
        };
        
        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
                
        Date effectiveDate = iter.hasNext() ? (Date) iter.next() : null;
        return effectiveDate;
    }
    
	/**
	 * Get date for the enrollment immediately following the date for
	 * the cancel decline record.
	 * 
	 * @param cancelDeclineDate
	 * @return
	 */
	private Date getEnrollmentDateForVerifiedEnrollmentAfter(EntityKey personId, Date cancelDeclineDate) 
	{
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		contextData.put("cancelDeclineDate", cancelDeclineDate);
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery(getEnDtForEarliestAfter_Query);
				q.setMaxResults(1);
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				q.setParameter("status", EnrollmentStatus.CODE_VERIFIED.getCode());
				q.setParameter("dateParam", getContextData().get("cancelDeclineDate"));

				return q.list();				
			}
		};
		
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
				
		Date enrollmentDate = iter.hasNext() ? (Date) iter.next() : null;
		return enrollmentDate;
	}
	
    /**
     * Get application date for the enrollment immediately following the date for
     * the cancel decline record.
     * 
     * @param cancelDeclineDate
     * @return
     */
    private Date getEnrollmentApplicationDateForSpecifiedStatusAfter(EntityKey personId,
            Date cancelDeclineDate, String status) {
        Map contextData = new HashMap();
        contextData.put("personId", personId);                                          
        contextData.put("cancelDeclineDate", cancelDeclineDate);
        contextData.put("status", status);
        HibernateCallback callback = new AbstractDAOAction(contextData) { 
            public Object execute(Session session) {
                Query q = session.getNamedQuery(getAppDtForEarliestAfter_Query);
                q.setMaxResults(1);
                q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
                q.setParameter("status", getContextData().get("status"));                
                q.setParameter("dateParam", getContextData().get("cancelDeclineDate"));

                return q.list();                
            }
        };
        
        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
                
        Date applicationDate = iter.hasNext() ? (Date) iter.next() : null;
        return applicationDate;
    }    
	
    private Date getEnrollmentApplicationDateForSpecifiedStatus(EntityKey personId, String status) 
    {
        Map contextData = new HashMap();
        contextData.put("personId", personId);
        contextData.put("status", status);
        HibernateCallback callback = new AbstractDAOAction(contextData) { 
            public Object execute(Session session) {
                Query q = session.getNamedQuery(getAppDtForEarliestWStatus_Query);
                q.setMaxResults(1);
                q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
                q.setParameter("status", getContextData().get("status"));

                return q.list();                
            }
        };
        
        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
            
        Date applicationDate = iter.hasNext() ? (Date) iter.next() : null;
        return applicationDate;
    }    
    
	/**
	 * Get date for the enrollment immediately following the date for
	 * the cancel decline record.
	 * 
	 * @param cancelDeclineDate
	 * @return
	 */
	private EnrollmentDetermination getPriorityGroupForVerifiedEnrollmentAfter(EntityKey personId, Date cancelDeclineDate) 
	{
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		contextData.put("cancelDeclineDate", cancelDeclineDate);
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery(getPrGrpForEarliestAfter_Query);
				q.setMaxResults(1);
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				q.setParameter("status", EnrollmentStatus.CODE_VERIFIED.getCode());
				q.setParameter("dateParam", getContextData().get("cancelDeclineDate"));

				return q.list();				
			}
		};
		
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
				
		EnrollmentDetermination enrollmentDetermination = iter.hasNext() ? (EnrollmentDetermination) iter.next() : null;
		return enrollmentDetermination;
	}
	
    /**
     * Returns the enrollment priority code and status code before PH was added. Used when letter 630D is triggered
     * @param personId
     * @return String[] with enrollment priority code and enrollment status code. Return null if not found.
     */
    public String[] getEnrollmentPriorityBeforePH(EntityKey personId) 
        throws DAOException 
    {
        Object[] results = null;
        String[] priority = null;
        
        Iterator iter = findByNamedQueryAndNamedParam(
                getPriorityGrpsBeforePH_Query,
                "personId", (BigDecimal) personId.getKeyValue())
                .iterator();        

        if (iter.hasNext()) {
            results = (Object[])iter.next(); 
            priority = new String[] {
                    results[0] == null ? "" : (String)results[0], 
                    results[1] == null ? "" : (String)results[1]};
        }
        return priority;
    }
	private Date getEnrollmentDateForEarliestVerifiedEnrollment(EntityKey personId) 
	{
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery(getEnDtForEarliestWStatus_Query);
				q.setMaxResults(1);
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				q.setParameter("status", EnrollmentStatus.CODE_VERIFIED.getCode());

				return q.list();				
			}
		};
		
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
			
		Date enrollmentDate = iter.hasNext() ? (Date) iter.next() : null;
		return enrollmentDate;
	}

   private Date getEffectiveDateForEarliestVerifiedEnrollment(EntityKey personId) 
    {
        Map contextData = new HashMap();
        contextData.put("personId", personId);                                          
        HibernateCallback callback = new AbstractDAOAction(contextData) { 
            public Object execute(Session session) {
                Query q = session.getNamedQuery(getEffectiveDateForEarliestWStatus_Query);
                q.setMaxResults(1);
                q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
                q.setParameter("status", EnrollmentStatus.CODE_VERIFIED.getCode());

                return q.list();                
            }
        };
        
        Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
            
        Date enrollmentDate = iter.hasNext() ? (Date) iter.next() : null;
        return enrollmentDate;
    }
	   
	private EnrollmentDetermination getPriorityGroupForEarliestVerifiedEnrollment(EntityKey personId) 
	{
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery(getPrGrpForEarliestWStatus_Query);
				q.setMaxResults(1);
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				q.setParameter("status", EnrollmentStatus.CODE_VERIFIED.getCode());

				return q.list();				
			}
		};
		
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
		EnrollmentDetermination enrollmentDetermination = iter.hasNext() ? (EnrollmentDetermination) iter.next() : null;
		return enrollmentDetermination;
	}
	
	/* (non-Javadoc)
	 * @see gov.va.med.esr.common.persistent.history.RulesEnrollmentHistoryDAO#isVerifiedEnrollmentExistsForMedicaidEligibility(gov.va.med.fw.model.EntityKey)
	 * DNS   doank: CCR8797
	 */
	public boolean isVerifiedEnrollmentExistsForMedicaidEligibility(EntityKey personId) {
		boolean exists = false;
		// execute the named query
		Map contextData = new HashMap();
		contextData.put("personId", personId);				        		        	
		
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery("contEnrollment_verifiedEnrollmentEligMedicaid");
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
				
		//Fetch the data of results are returned
		if (iter.hasNext()) {
			exists = true;
		}
		return exists;
	}
	
	public List getPersonEnrollmentDeterminationHistory(EntityKey personId)
			throws DAOException {

		return getEnrollmentDeterminationHistory(personId);

	}
	
	private List getEnrollmentDeterminationHistory(EntityKey personId) 
	{
		Map contextData = new HashMap();
		contextData.put("personId", personId);	
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery(getPersonEnrollHistory_Query);				
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				return q.list();				
			}
		};
		
		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
		
		ArrayList enrollmentDeterminations = new ArrayList();
		EnrollmentDetermination enrollmentDetermination = null;        
        
        while (iter.hasNext()) {
            Object row = iter.next();
            if (row != null) {
                enrollmentDetermination = (EnrollmentDetermination) row;
                enrollmentDeterminations.add(enrollmentDetermination);
            }
        }				
		
		return enrollmentDeterminations;
	}
	
	public boolean getPriorToEnrDetermHistory(EntityKey personId, Date beforeDate, Date recModifiedDate) throws DAOException{
		
		return getEnrDetermHistoryPriorToDate(personId, beforeDate, recModifiedDate);
		
	}
	
	private boolean getEnrDetermHistoryPriorToDate(EntityKey personId, Date beforeDate, Date recModifiedDate) 
	{
		Map contextData = new HashMap();
		contextData.put("personId", personId);
		contextData.put("dateParam", beforeDate);
		contextData.put("recModifiedDate", recModifiedDate);
		HibernateCallback callback = new AbstractDAOAction(contextData) { 
			public Object execute(Session session) {
				Query q = session.getNamedQuery(getPriorToEnrollHistory_Query);				
				q.setParameter("personId", ((EntityKey) getContextData().get("personId")).getKeyValue());
				q.setParameter("dateParam", getContextData().get("dateParam"));
				q.setParameter("status", EnrollmentStatus.CODE_VERIFIED.getCode());
				q.setParameter("recModifiedDate", getContextData().get("recModifiedDate"));
				return q.list();				
			}
		};
		
		List results = this.getHibernateTemplate().executeFind(callback);
		
		if(results.size() > 0){
			return true;
		}
		else{
			return false;
		}
		
		
	}

	
	
}
