/*
 * Created on Jan 11, 2005
 *
 * Test cases directly related Person
 */
package gov.va.med.esr.common.persistent.history;

import java.util.Date;
import java.util.Iterator;
import java.util.Map;


import gov.va.med.esr.common.model.ee.MonetaryBenefitAward;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.lookup.EnrollmentStatus;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.persistent.history.AbstractHistoryTestCase;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.persistent.DAOException;

/**
 * @author DNS   CHENJ2
 * 
 * Test history directly related to Phone email address
 */
public class RulesEnrollmentHistoryTest extends AbstractHistoryTestCase {

	private static String personId = "373971922";

	private static String historyDAOName = "rulesEnrollmentHistoryDAO";

	private RulesEnrollmentHistoryDAO getRulesEnrollmentHistoryDAO()
	{
		return (RulesEnrollmentHistoryDAO)getHistoryDAO();
	}
	
	public void testGetAppDateForMostRecentUnverifiedEnrollment() throws DAOException {
		//long t1 = System.currentTimeMillis();
		Date applicationDate = getRulesEnrollmentHistoryDAO().getAppDateForMostRecentUnverifiedEnrollment(getPersonKey());
		//long t2 = System.currentTimeMillis();
		//System.out.println("Retrieved history entry, Elapsed time = " + (t2-t1));
		System.out.println("Application Date = " + applicationDate);
	}
	
//    public void testGetAppDateForEarliestUnverifiedEnrollment() throws DAOException {
//        //long t1 = System.currentTimeMillis();
//        Date applicationDate = getRulesEnrollmentHistoryDAO().getEnrollmentApplicationDateForEarliestSpecifiedStatusUnlessCancelled(getPersonKey());
//        //long t2 = System.currentTimeMillis();
//        //System.out.println("Retrieved history entry, Elapsed time = " + (t2-t1));
//        System.out.println("Application Date = " + applicationDate);
//    }    
    
	public void testGetFirstNotNullEffDate() throws DAOException {
		Date effectiveDate = getRulesEnrollmentHistoryDAO().getFirstNotNullEffDate(getPersonKey());
		System.out.println("Effective Date = " + effectiveDate);
	}
	
	public void testGetPersonForPriorEnrollment() throws DAOException {
		Person p = getRulesEnrollmentHistoryDAO().getPersonForPriorEnrollment(getPersonKey());
		printHistoryData(p);
	}
	
	public void testGetEnrollmentDateForEarliestVerifiedUnlessCancelled() throws DAOException {
		Date enrollmentDate = getRulesEnrollmentHistoryDAO().getEnrollmentDateForEarliestVerifiedUnlessCancelled(getPersonKey());
		System.out.println("Enrollment Date = " + enrollmentDate);
		
	}

	public void testIsVerifiedEnrollmentExists() throws DAOException {
		boolean exists = getRulesEnrollmentHistoryDAO().isVerifiedEnrollmentExists(getPersonKey());
		System.out.println((exists?"Found":"Did not find") + " verified enrollment.");
		
	}

	public void testGetHistory() {
		// do nothing
	}
	
	protected void verifyRetrievedHistoryData(Person p) {
	}

	protected void printHistoryData(Person p) {
		if (p != null) {
			printProperty("EnrollmentDetermination", p
					.getEnrollmentDetermination());
			printProperty("application", p.getApplication());
			printProperty("serviceConnectionAward", p
					.getServiceConnectionAward());
			MonetaryBenefitAward mb = p.getMonetaryBenefitAward();
			printProperty("monetaryBenefitAward", mb);
			if (mb != null) {
				printSet("monetaryBenefits", mb.getMonetaryBenefits());
			}
			printSet("SpecialFactors", p.getSpecialFactors());
			printSet("PurpleHearts", p.getDecorations());
			printProperty("PrisonerOfWar", p.getPrisonerOfWar());

			Map incomeTests = p.getIncomeTests();
			IncomeTest incomeTest = null;
			Iterator iter = incomeTests.keySet().iterator();
			if (iter != null & iter.hasNext()) {
				incomeTest = (IncomeTest) incomeTests.get(iter.next());
			}
			printProperty("IncomeTest", incomeTest);
			if (incomeTest != null) {
				printSet("IncomeTestStatues", incomeTest.getStatuses());
			}
		}
	}

	public void testGetStatusAndAppDateForEarliest() throws DAOException {
		Object[] results = getRulesEnrollmentHistoryDAO().getStatusAndAppDateForEarliest(getPersonKey());
		
		EnrollmentStatus status = null;
		Date appDate = null;
		
		if (results != null) {
			status = (EnrollmentStatus)results[0];
			appDate = (Date)results[1];
		}
		System.out.println("enrollment status = " + status);
		System.out.println("application Date = " + appDate);
	}

	/**
	 *
	 * @throws DAOException
	 */
	public void testGetPriorityGrpsForMostRecent() throws DAOException {
		String[] results = null;
		
		/* Performance results for trying 3 different versions of the query:
			 * testGetPriorityGrpsForMostRecent: queryNum=1
			 * Test Elapsed time = 537
			 * testGetPriorityGrpsForMostRecent: queryNum=2
			 * PTest Elapsed time = 3382
			 * testGetPriorityGrpsForMostRecent: queryNum=3
			 * Test Elapsed time = 298
	
		long t1=0, t2=0;
		for (int i=0; i<3; i++) {
			System.out.println("testGetPriorityGrpsForMostRecent: queryNum=" + (i+1));
			t1 = System.currentTimeMillis();
			// run each test 50 times
			for (int j=0;j<50;j++) {
				results = getRulesEnrollmentHistoryDAO().getPriorityGrpsForMostRecent(getPersonKey(), i+1);
			}
			t2 = System.currentTimeMillis();

			if (results != null) {
				System.out.println("Priority Group= " + results[0]);
				System.out.println("Priority Sub Group = " + results[1]);
			}
			System.out.println("Test Elapsed time = " + (t2-t1)/50);
		}*/
		
		results = getRulesEnrollmentHistoryDAO().getPriorityGrpsForMostRecent(getPersonKey());
		if (results != null) {
			System.out.println("Priority Group= " + results[0]);
			System.out.println("Priority Sub Group = " + results[1]);
		}
	}

	protected String getHistoryDAOName() {
		return historyDAOName;
	}

	protected String getPersonId() {
		return personId;
	}

	//----- Query performance testing --------//
	/* The following queries were tested:
	 * 
	 * 	<sql-query name="enrollmentHistoryQuery_GetDateForPrevious_sql">
		<return-scalar column="RECORD_MODIFIED_DATE" type="timestamp"/>
			SELECT RECORD_MODIFIED_DATE
				FROM (SELECT RANK() OVER (ORDER BY e.RECORD_MODIFIED_DATE DESC) as en_rank, e.RECORD_MODIFIED_DATE
					  FROM ENROLLMENT_DETERMINATION_H e
					  WHERE e.PERSON_ID = :personId)
				WHERE en_rank = 2
	</sql-query>

	<query name="enrollmentHistoryQuery_GetDateForPrevious_hql">
		<![CDATA[
		SELECT max(e.modifiedOn)
		FROM EnrollmentDetermination as e
 		WHERE e.person.identifier = :personId
			AND e.modifiedOn < (
				SELECT MAX(e1.modifiedOn) 
				FROM EnrollmentDetermination as e1
				WHERE e1.person.identifier = :personId)
		]]>
	</query>

	<query name="enrollmentHistoryQuery_GetDateForPrevious_hql1">
		<![CDATA[
		SELECT e.modifiedOn
		FROM EnrollmentDetermination as e
 		WHERE e.person.identifier = :personId
			AND e.modifiedOn < (
				SELECT MAX(e1.modifiedOn) 
				FROM EnrollmentDetermination as e1
				WHERE e1.person.identifier = :personId)
		ORDER BY a.modifiedOn DESC, a.historyId DESC		
		]]>
	</query>

	 * 
	 * Testing results:
	 * 	Testing GetDateForpriorEnrollment with hql
	 	Retrieved history data, Avg elapsed time = 321
	 	Testing GetDateForpriorEnrollment with sql
	 	Retrieved history data, Avg elapsed time = 260
	 */
	/*public void TestPerfGetDateForPriorEnrollment() throws DAOException
	{
		String queryBaseName = "enrollmentHistoryQuery_GetDateForPrevious";
		runQuery(queryBaseName, "hql1", null);
		runQuery(queryBaseName, "hql", null);
		runQuery(queryBaseName, "sql", null);
	}
	
	private void runQuery(String queryBaseName, String queryType, String enrollmentStatus) throws DAOException {
		String queryName = queryBaseName + "_" + queryType;
		System.out.println("Running query: " + queryName);
		
		ChangeEvent changeEvent = null;
		
		long t1 = System.currentTimeMillis();
		for (int i=0; i<50; i++) 
			changeEvent  = getRulesEnrollmentHistoryDAO().getHistoryChangeEventForQuery(queryName, getPersonKey(), enrollmentStatus);	
		long t2 = System.currentTimeMillis();
		System.out.println("Retrieved history data, Avg elapsed time = " + (t2-t1)/50);
		
		System.out.println("Date of prior enrollment =" + changeEvent.getTimeStamp());

	}*/
	
	/**
	 * Performance test for queries
	 * 
	 * The following queries were tested:
	 * 	<query name="enrollmentHistoryQuery_GetDateForMostRecentWStatus_hql">
		SELECT max(e.modifiedOn)
  		FROM EnrollmentDetermination as e
 		WHERE e.person.identifier = :personId
			AND	e.historyId IN (
			SELECT  MAX (e1.historyId)
              FROM EnrollmentDetermination e1
				where e1.person.identifier = :personId
            GROUP BY e1.modifiedOn)
		AND e.enrollmentStatus.code = :status
		ORDER BY e.modifiedOn DESC
	</query>
	
	<query name="enrollmentHistoryQuery_GetDateForMostRecentWStatus_hql1">
		SELECT e.modifiedOn
  		FROM EnrollmentDetermination as e
 		WHERE e.person.identifier = :personId
			AND	e.historyId IN (
			SELECT  MAX (e1.historyId)
              FROM EnrollmentDetermination e1
				where e1.person.identifier = :personId
            GROUP BY e1.modifiedOn)
		AND e.enrollmentStatus.code = :status
		ORDER BY e.modifiedOn DESC
	</query>

	<query name="enrollmentHistoryQuery_GetDateForMostRecentWStatus_hql2">
		SELECT e.modifiedOn
  		FROM EnrollmentDetermination as e
 		WHERE e.historyId IN (
			SELECT  MAX (e1.historyId)
              FROM EnrollmentDetermination e1
				where e1.person.identifier = :personId
            GROUP BY e1.modifiedOn)
		AND e.enrollmentStatus.code = :status
		ORDER BY e.modifiedOn DESC
	</query>

	Results: surprisingly the one that does not filter on person first offers the
	 best performance.  
	 
		Running query: enrollmentHistoryQuery_GetDateForMostRecentWStatus_hql
		Retrieved history data, Avg elapsed time = 355

		Running query: enrollmentHistoryQuery_GetDateForMostRecentWStatus_hql1
		Retrieved history data, Avg elapsed time = 358

		Running query: enrollmentHistoryQuery_GetDateForMostRecentWStatus_hql2
		Retrieved history data, Avg elapsed time = 269

	 * @throws DAOException
	 */
	/*public void TestPerfGetDateForMostRecentVerifiedEnrollment() throws DAOException
	{
		String queryBaseName = "enrollmentHistoryQuery_GetDateForMostRecentWStatus";
		runQuery(queryBaseName, "hql", "2");
		runQuery(queryBaseName, "hql1", "2");
		runQuery(queryBaseName, "hql2", "2");
	}

	public void TestPerfGetDateForMostRecentUnVerifiedEnrollment() throws DAOException
	{
		String queryBaseName = "enrollmentHistoryQuery_GetDateForMostRecentWStatus";
		runQuery(queryBaseName, "hql", "1");
		runQuery(queryBaseName, "hql1", "1");
		runQuery(queryBaseName, "hql2", "1");
	}*/

}