package gov.va.med.esr.common.rule.service;

import java.math.BigDecimal;

import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.common.model.comms.CommsLogEntry;
import gov.va.med.esr.common.model.comms.CommsTemplate;

import gov.va.med.esr.common.model.ee.MilitaryService;
import gov.va.med.esr.common.model.ee.PurpleHeart;
import gov.va.med.esr.common.model.ee.RadiationExposure;
import gov.va.med.esr.common.model.ee.Eligibility;
import gov.va.med.esr.common.model.financials.IncomeTestStatus;
import gov.va.med.esr.common.model.ee.AgentOrangeExposure;
import gov.va.med.esr.common.model.ee.SHAD;
import gov.va.med.esr.common.model.ee.PurpleHeartDocument;
import gov.va.med.esr.common.clock.Clock;
import gov.va.med.esr.common.model.comms.AacLetterRequest;
import gov.va.med.esr.common.model.lookup.AgentOrangeExposureLocation;
import gov.va.med.esr.common.model.lookup.ComLetterType;
import gov.va.med.esr.common.model.lookup.DecorationStatus;
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.lookup.RadiationExposureMethod;
import gov.va.med.esr.common.model.lookup.Indicator;
import gov.va.med.esr.common.model.lookup.EligibilityType;
import gov.va.med.esr.common.model.lookup.ComLetterTemplateType;
import gov.va.med.esr.common.model.lookup.MeansTestStatus;
import gov.va.med.esr.common.model.lookup.IncomeTestType;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.lookup.SSAVerificationStatus;

import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.common.model.person.id.PersonIdEntityKeyImpl;
import gov.va.med.esr.common.persistent.comms.CommsTemplateDAO;
import gov.va.med.esr.common.util.CommsLetterConstants;
import gov.va.med.esr.common.util.RuleAbstractTestCase;
import gov.va.med.esr.service.CommsLogService;

public class AutomaticLetterTest extends RuleAbstractTestCase {

    public AutomaticLetterTest(String testName) {
        super(testName);
        // TODO Auto-generated constructor stub
    }

    public void testTrigger_292() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        Person incoming = this.savePerson(onFile);

        this.getCommunicationRuleService().triggerAutomaticLetters(incoming,
                Clock.Type.SSN_30_DAY_PSEUDO_SSN_REASON_CLOCK,
                AacLetterRequest.DEPENDENT_LETTER);
    }

    public void testTrigger_293() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        Person incoming = this.savePerson(onFile);

        this.getCommunicationRuleService().triggerAutomaticLetters(incoming,
                Clock.Type.SSN_30_DAY_PSEUDO_SSN_VERIFICATION_CLOCK,
                AacLetterRequest.SPOUSE_LETTER);
    }

    public void testTrigger_290() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        
        Person updated = this.getPersonService().save(onFile);
        Person incoming = (Person)updated.clone();
        assertNull(onFile.getOfficialSsn());        
        SSN ssn = this.createSSN(); 
        ssn.setType(this.getLookupService().getSSNTypeByCode(SSNType.CODE_ACTIVE.getName()));
        ssn.setSsaVerificationStatus(this.getLookupService().getSSAVerificationStatusByCode(SSAVerificationStatus.INVALID_PER_SSA.getName()));
        incoming.addSsn(ssn);
        Person result = this.getDemographicService().updateIdentityTraits(incoming);
        assertNotNull(result.getOfficialSsn());
    }    
    
    public void testTrigger_291() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        Person incoming = this.savePerson(onFile);

        this.getCommunicationRuleService().triggerAutomaticLetters(incoming,
                Clock.Type.SSN_30_DAY_VALIDATION_CLOCK,
                AacLetterRequest.SPOUSE_LETTER);
    }

    public void testTrigger_600C() throws Exception {
        Person onFile = this.buildSimplePerson();
        Person incoming = this.savePerson(onFile);

        this.doVerifiedTests(incoming, EnrollmentPriorityGroup.GROUP_1);
    }
    
    public void testTrigger_601B_1() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        onFile.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_CANCELLED_DECLINED.getCode()));        
        this.setEligibilityStatusToVerified(onFile);        
        Person incoming = this.savePerson(onFile);
        incoming.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_NOT_ELIGIBLE_REFUSED_TO_PAY_COPAY.getCode()));
        this.doMiscEnrollmentStatusTests(incoming, EnrollmentPriorityGroup.GROUP_1);
    }
    
    public void testTrigger_601B_2() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEligibilityStatusToPendingVerification(onFile);
        onFile.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_NOT_ELIGIBLE_REFUSED_TO_PAY_COPAY.getCode()));        
        Person incoming = this.savePerson(onFile);
     
        this.setEligibilityStatusToVerified(incoming);
        this.doMiscEnrollmentStatusTests(incoming, EnrollmentPriorityGroup.GROUP_1);
    }    
    
    public void testTrigger_601B_3() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEligibilityStatusToPendingVerification(onFile);
        onFile.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_PENDING.getCode()));        
        Person incoming = this.savePerson(onFile);
        incoming.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_NOT_ELIGIBLE_REFUSED_TO_PAY_COPAY.getCode()));     
        this.setEligibilityStatusToVerified(incoming);
        this.doMiscEnrollmentStatusTests(incoming, EnrollmentPriorityGroup.GROUP_1);
    }        
    
    public void testTrigger_601B_Neg() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        onFile.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_NOT_ELIGIBLE_REFUSED_TO_PAY_COPAY.getCode()));
        this.setEligibilityStatusToVerified(onFile);
        Person incoming = this.savePerson(onFile);
        this.doMiscEnrollmentStatusTests(incoming, EnrollmentPriorityGroup.GROUP_1);
    }        

    public void testTrigger_600D() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachMilitaryServiceEpisode(onFile);
        this.attachPharmacyCopayTestWithRXCopayExempt(onFile);
        Person incoming = this.savePerson(onFile);

        this.doVerifiedTests(incoming, EnrollmentPriorityGroup.GROUP_2);
    }
    
    public void testTrigger_600D_canceled() throws Exception {
        doTrigger600D(EnrollmentStatus.CODE_CANCELLED_DECLINED.getCode());
    }
    
    public void testTrigger_600D_initialApp() throws Exception {
        doTrigger600D(EnrollmentStatus.CODE_REJECTED_INITIAL_APPLICATION_BY_VAMC.getCode());
    }
    
    public void testTrigger_600D_belowEGT() throws Exception {
        doTrigger600D(EnrollmentStatus.CODE_REJECTED_BELOW_ENROLLMENT_GROUP_THRESHOLD.getCode());
    }        
    
    public void testTrigger_600D_refuse() throws Exception {
        doTrigger600D(EnrollmentStatus.CODE_NOT_ELIGIBLE_REFUSED_TO_PAY_COPAY.getCode());
    }            
    
    public void testTrigger_600D_inelig() throws Exception {
        doTrigger600D(EnrollmentStatus.CODE_NOT_ELIGIBLE_INELIGIBLE_DATE.getCode());
    }                
    
    
    public void testTrigger_600Dand600C_neg() throws Exception {
        doTrigger600D(EnrollmentStatus.CODE_VERIFIED.getCode());
    }        
    
    private void doTrigger600D(String status) throws Exception {
        PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(new BigDecimal("148832"));        
        Person onFile = this.getPersonService().getPerson(personKey);        
        this.setEligibilityStatusToVerified(onFile);
        this.attachMilitaryServiceEpisode(onFile);
        this.attachPharmacyCopayTestWithRXCopayExempt(onFile);
        this.attachCancelDecline(onFile);
        onFile.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(status));
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);
        Person incoming = this.savePerson(onFile);
        incoming.setCancelDecline(null);
        incoming.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_VERIFIED.getCode()));
        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_8);
        this.doVerifiedTests(incoming, EnrollmentPriorityGroup.GROUP_2);        
    }
    
    public void testTrigger_600D_MT_Primary() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachMilitaryServiceEpisode(onFile);
        this.attachMeansTestWithMtCopayRequired(onFile, new BigDecimal(1), new BigDecimal(1));
        IncomeTestStatus status = new IncomeTestStatus();
        status.setDeterminedStatus(this.getLookupService().getMeansTestStatusByCode(MeansTestStatus.MT_STATUS_EXEMPT.getCode()));
        status.setStatus(this.getLookupService().getMeansTestStatusByCode(MeansTestStatus.MT_STATUS_EXEMPT.getCode()));
        status.setType(this.getLookupService().getIncomeTestTypeByCode(IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST.getCode()));
        onFile.getIncomeTest(new Integer(2005)).addStatus(status);
        Person incoming = this.savePerson(onFile);

        this.doVerifiedTests(incoming, EnrollmentPriorityGroup.GROUP_2);
    }    

    /** Trigger604A  - One Time Notification of Conversion to Priority 8

    IF
    the user enrollee valid through date has been updated from NULL
    AND
    The current enrollment priority group is equal to PG8
    AND
    The current means test status is equal to MT Copay Required
    THEN
    Trigger the mailing of the 604A letter

    */    
    public void testTrigger_604A_withAppDate() throws Exception {

        PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(new BigDecimal("20433657"));        
        Person onFile = this.getPersonService().getPerson(personKey);        

        this.attachApplication(onFile);
        onFile.getApplication().setApplicationDate(this.getDate(2002,1,1));
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);        
        this.attachMeansTestWithMtCopayRequired(onFile, new BigDecimal(100),
                new BigDecimal(100));
        this.setEligibilityStatusToVerified(onFile);
        Person incoming = savePerson(onFile);
        incoming.setUserEnrolleeValidThrough(new Integer(2006));

        this.doTriggerLetter(incoming);
    }
    
    public void testTrigger_604A_withEffDate() throws Exception {

        Person incoming = this.getPerson("");

        incoming.setUserEnrolleeValidThrough(new Integer(2006));

        this.doTriggerLetter(incoming);
    }    
    
    public void create604APersonWithEffDate() throws Exception {

        Person onFile = this.buildSimplePerson();

        this.attachVerifiedEnrollment(onFile);
        onFile.getEnrollmentDetermination().setEffectiveDate(this.getDate(2002,1,1));
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);        
        this.attachMeansTestWithMtCopayRequired(onFile, new BigDecimal(100),
                new BigDecimal(100));
        this.setEligibilityStatusToVerified(onFile);
        Person incoming = savePerson(onFile);
        this.setComplete();
        System.out.println("Person id="
                + incoming.getPersonEntityKey().getKeyValueAsString());        
    }    
    
    public void testTrigger_604A_neg() throws Exception {

        Person onFile = this.buildSimplePerson();

        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);        
        this.attachMeansTestWithNoLongerRequired(onFile);
        this.setEligibilityStatusToVerified(onFile);
        Person incoming = savePerson(onFile);
        incoming.setUserEnrolleeValidThrough(new Integer(2006));

        this.doTriggerLetter(incoming);
    }    
    
    
    
    /** Trigger640D – MT Change Notification

    IF NEW ENROLLMENT PRIORITY:
    From Priority to Priority:
    5 to 6
    5 to 7
    5 to 8
    6 to 5
    7 to 8
    7 to 5
    8 to 7
    8 to 5
    Based on MT status change not eligibility
    factor change:
    Note: If a null priority group is encountered in the immediate prior enrollment record, locate the most recent non-null priority group for comparison'

    AND (PRIOR ENROLLMENT PRIORITY Not a NULL Priority and Not equal to the new priority)

    AND (NSC or (SC<50% and SC%=0))

    THEN
    Trigger the mailing of the 640D letter

    */
    public void testTrigger_640D_1() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_8, EnrollmentPriorityGroup.GROUP_5);
    }
    public void testTrigger_640D_2() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_8, EnrollmentPriorityGroup.GROUP_7);
    }
    public void testTrigger_640D_3_Neg() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_8, EnrollmentPriorityGroup.GROUP_4);
    }
    public void testTrigger_640D_4() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_7, EnrollmentPriorityGroup.GROUP_8);
    }
    public void testTrigger_640D_5() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_7, EnrollmentPriorityGroup.GROUP_5);
    }
    public void testTrigger_640D_6() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_6, EnrollmentPriorityGroup.GROUP_5);
    }
    public void testTrigger_640D_7_Neg() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_6, EnrollmentPriorityGroup.GROUP_4);
    }
    public void testTrigger_640D_8() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_5, EnrollmentPriorityGroup.GROUP_6);
    }
    public void testTrigger_640D_9_Neg() throws Exception {
        testTrigger_640D(EnrollmentPriorityGroup.GROUP_5, EnrollmentPriorityGroup.GROUP_4);
    }                      
    private void testTrigger_640D(EnrollmentPriorityGroup.Code onfileP, EnrollmentPriorityGroup.Code incomingP) throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, onfileP);
        this.attachMeansTestWithMtCopayRequired(onFile, new BigDecimal(100),
                new BigDecimal(100));
        Eligibility e = new Eligibility();
        e.setType(this.getLookupService().getEligibilityTypeByCode(
                EligibilityType.NSC.getCode()));
        onFile.getEnrollmentDetermination().setPrimaryEligiblity(e);
        Person incoming = this.savePerson(onFile);

        this.attachMeansTestWithGmtCopayRequired(incoming, new BigDecimal(1),
                new BigDecimal(2));

        this.setEnrollmentPriority(incoming, incomingP);

        doTriggerLetter(incoming);
    }    

    public void testTrigger_640D_Neg() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);
        this.attachMeansTestWithMtCopayRequired(onFile, new BigDecimal(100),
                new BigDecimal(100));
        Eligibility e = new Eligibility();
        e.setType(this.getLookupService().getEligibilityTypeByCode(
                EligibilityType.NSC.getCode()));
        onFile.getEnrollmentDetermination().setPrimaryEligiblity(e);
        Person incoming = this.savePerson(onFile);
        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_5);

        doTriggerLetter(incoming);
    }

 

    public void testTrigger_640C() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);
        Person incoming = this.savePerson(onFile);
        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_3);
        this.attachPrisonerOfWar(incoming, ImpreciseDateUtils
                .createImpreciseDate(1943, 1, 1), ImpreciseDateUtils
                .createImpreciseDate(1944, 1, 1));

        doTriggerLetter(incoming);
    }

    public void testTrigger_640C_Neg() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);
        Person incoming = this.savePerson(onFile);
        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_3);

        doTriggerLetter(incoming);
    }

    public void createCommsLogWith600B() throws Exception {
        Person onFile = this.buildSimplePerson();
        Person incoming = this.savePerson(onFile);
        insertCommsLogEntry(incoming, ComLetterTemplateType.FORM_NUMBER_600B
                .getCode());
        this.setComplete();
        System.out.println("Person id="
                + incoming.getPersonEntityKey().getKeyValueAsString());
    }

    /**
     * if p = 7 or 8 and CV End Date has expired and prior P = 6 and enroll
     * status = V and does not include CV eligibility and Previously Mailed 600B
     * or 600C or 600D then send 640V
     */
    public void testTrigger_640V() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_6);
        this.attachCV(onFile);
        Person incoming = this.savePerson(onFile);
        incoming.setMilitaryService(null);
        this.attachExpiredCV(incoming);

        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_8);

        doTriggerLetter(incoming);
    }

    public void testTrigger_640V_Neg() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_6);
        this.attachCV(onFile);
        Person incoming = this.savePerson(onFile);

        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_8);

        doTriggerLetter(incoming);
    }

    private void attachCV(Person person) throws Exception {
        MilitaryService ms = this.attachMilitaryService(person);
        ms.setCombatVeteranEligibilityEndDate(this.getDate(2007, 1, 1));
    }

    private void attachExpiredCV(Person person) throws Exception {
        MilitaryService ms = this.attachMilitaryService(person);
        ms.setCombatVeteranEligibilityEndDate(this.getDate(2006, 1, 1));
    }

    /**
     * if prior enroll status = 7 or 8 and include SHAD and enroll status = V
     * and P=6 and Previously Mailed 600B or 600C or 600D then send 640G
     */
    public void testTrigger_640G() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_7);

        Person incoming = this.savePerson(onFile);
        incoming.setShad(new SHAD());
        incoming.getShad().setShadIndicator(
                this.getLookupService().getIndicatorByCode(Indicator.YES));

        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_6);

        doTriggerLetter(incoming);
    }

    /**
     * if p = 7 or 8 and prior P=6 and prior AO = Yes and enroll status = V and
     * AO location was other than Vietnam and Previously Mailed 600B or 600C or
     * 600D then send 640H
     */
    public void testTrigger_640H() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_6);
        AgentOrangeExposure ao = this.createAgentOrange();
        ao.setLocation(this.getLookupService()
                .getAgentOrangeExposureLocationByCode(
                        AgentOrangeExposureLocation.CODE_VIETNAM.getName()));
        onFile.addSpecialFactor(ao);

        Person incoming = this.savePerson(onFile);
        ((AgentOrangeExposure) incoming
                .getSpecialFactorByType(AgentOrangeExposure.class))
                .setLocation(this.getLookupService()
                        .getAgentOrangeExposureLocationByCode(
                                AgentOrangeExposureLocation.CODE_KOREAN_DMZ
                                        .getName()));

        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_7);

        doTriggerLetter(incoming);
    }

    /**
     * if P = 7 or 8 and prior P = 6 and Radiation = Yes and Radiation Exposure
     * Method is other than Nagasaki/Hiroshima or, Atmospheric Nuclear Testing
     * or, H/N and Atmospheric Testing and enroll status = V and Previously
     * Mailed 600B or 600C or 600D then send 640I
     */
    public void testTrigger_640I() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_6);
        RadiationExposure radiationExposure = new RadiationExposure();
        radiationExposure
                .setExposureMethod(this
                        .getLookupService()
                        .getRadiationExposureMethodByCode(
                                RadiationExposureMethod.CODE_ATMOSPHERIC_NUCLEAR_TESTING
                                        .getName()));
        radiationExposure.setRadiationExposureIndicator(this.getLookupService()
                .getIndicatorByCode(Indicator.YES));
        onFile.addSpecialFactor(radiationExposure);

        Person incoming = this.savePerson(onFile);
        incoming.removeSpecialFactorByType(RadiationExposure.class);
        RadiationExposure replace = new RadiationExposure();
        replace
                .setExposureMethod(this
                        .getLookupService()
                        .getRadiationExposureMethodByCode(
                                RadiationExposureMethod.CODE_UNDERGROUND_NUCLEAR_TESTING
                                        .getName()));
        replace.setRadiationExposureIndicator(this.getLookupService()
                .getIndicatorByCode(Indicator.YES));
        incoming.addSpecialFactor(replace);

        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_7);

        doTriggerLetter(incoming);
    }

    private void doVerifiedTests(Person person,
            EnrollmentPriorityGroup.Code code) throws Exception {
        Person p = (Person) person.clone();
        this.attachVerifiedEnrollment(p);
        this.setEnrollmentPriority(p, code);
        doTriggerLetter(p);
    }
    
    private void doMiscEnrollmentStatusTests(Person person,
            EnrollmentPriorityGroup.Code code) throws Exception {
        Person p = (Person) person.clone();
        this.setEnrollmentPriority(p, code);
        doTriggerLetter(p);
    }    

    private void doTriggerLetter(Person person) throws Exception {
        this.getCommunicationRuleService().triggerAutomaticLetters(person, null, false, null);
    }

    protected void setEnrollmentPriority(Person person,
            EnrollmentPriorityGroup.Code type) throws Exception {
        person.getEnrollmentDetermination().setPriorityGroup(
                this.getLookupService().getEnrollmentPriorityGroupByCode(
                        type.getName()));
    }

    private void insertCommsLogEntry(Person person, String form)
            throws Exception {

        try {

            this.getLoginManager().loginAnonymous();
            CommsLogEntry log = new CommsLogEntry();

            Address addr = new Address();
            addr.setLine1("5400 Legacy Dr");
            addr.setLine2("A3-2B-06");
            addr.setLine3("Line3");
            addr.setCity("Plano");
            addr.setCounty("Collin");
            addr.setCountry("US");
            addr.setProvince("Province");
            addr.setZipPlus4("1234");
            addr.setState("TX");
            addr.setZipCode("75028");

            log.setAddress(addr);

            log.setLogXML("This is logXML");
            log.setPersonId(new BigDecimal(person.getEntityKey()
                    .getKeyValueAsString()));
            log.setRecipient(CommsLetterConstants.RECIPIENT_VETERAN);
            log.setLetterType(this.getLookupService().getComLetterTypeByCode(ComLetterType.CODE_ENROLLMENT.getCode()));

            CommsTemplateDAO dao = ((CommsTemplateDAO) applicationContext.getBean("commsTemplateDAO"));
            CommsTemplate templ = (CommsTemplate) dao
                    .findTemplateListByFormNumber(form).get(0);
            log.setTemplate(templ);

            CommsLogService logService = (CommsLogService) applicationContext.getBean("commsLogService");
            logService.insert(log);

        } catch (Exception e) {
            fail("Failed to insert a log entry due to exception", e);
        }

    }

    // ///////////////////
    /**
     * IF The Purple Heart documentation Acceptable indicator has changed to NO
     * AND the current Purple Heart indicator is equal to YES AND The Purple
     * Heart status is equal to Initial Letter Sent AND It is not true that The
     * previous purple heart status is equal to Initial Letter Sent
     */
    public void testTrigger_630A() throws Exception {

        Person onFile = this.buildSimplePerson();

        this.attachVerifiedEnrollment(onFile);
        this.attachPurpleHeartWithPHStatusPending(onFile);
        PurpleHeartDocument doc = this.createPHDocument();
        doc.setAcceptable(Boolean.TRUE);
        onFile.getPurpleHeart().addDocument(doc);
        this.setPurpleHeartStatus(DecorationStatus.CODE_IN_PROGRESS, onFile);
        this.setEligibilityStatusToVerified(onFile);
        Person incoming = savePerson(onFile);
        this.setPurpleHeartStatus(DecorationStatus.CODE_INITIAL_LETTER_SENT,
                incoming);
        ((PurpleHeartDocument) incoming.getPurpleHeart().getDocuments()
                .iterator().next()).setAcceptable(Boolean.FALSE);
        this.doTriggerLetter(incoming);
    }
    
    public void testTrigger_630C() throws Exception {

        Person onFile = this.buildSimplePerson();

        this.attachVerifiedEnrollment(onFile);
        this.attachPurpleHeartWithPHStatusPending(onFile);
        PurpleHeartDocument doc = this.createPHDocument();
        doc.setAcceptable(Boolean.TRUE);
        onFile.getPurpleHeart().addDocument(doc);
        this.setPurpleHeartStatus(DecorationStatus.CODE_IN_PROGRESS, onFile);
        this.setEligibilityStatusToVerified(onFile);
        Person incoming = savePerson(onFile);
        this.setPurpleHeartStatus(DecorationStatus.CODE_REJECTED,
                incoming);
        ((PurpleHeartDocument) incoming.getPurpleHeart().getDocuments()
                .iterator().next()).setAcceptable(Boolean.FALSE);
        
        this.getCommunicationRuleService().triggerAutomaticLetters(incoming, Clock.Type.PH_37_DAY_CLOCK, null);

    }    
    
    public void testTrigger_623A() throws Exception {

        Person onFile = this.buildSimplePerson();
        this.setEligibilityStatusToVerified(onFile);
        Person incoming = savePerson(onFile);
        this.attachVerifiedEnrollment(incoming);        
        incoming.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_REJECTED_BELOW_ENROLLMENT_GROUP_THRESHOLD.getCode()));        
        this.doTriggerLetter(incoming);
    }
    
    public void testTrigger_623D() throws Exception {

        Person onFile = this.buildSimplePerson();
        this.setEligibilityStatusToVerified(onFile);
        this.attachVerifiedEnrollment(onFile);        
        Person incoming = savePerson(onFile);
        insertCommsLogEntry(incoming, ComLetterTemplateType.FORM_NUMBER_600C.getCode());        
       
        incoming.getEnrollmentDetermination().setEnrollmentStatus(this.getLookupService().getEnrollmentStatusByCode(EnrollmentStatus.CODE_REJECTED_BELOW_ENROLLMENT_GROUP_THRESHOLD.getCode()));        
        this.doTriggerLetter(incoming);
    }        

    /**
     * IF The current Purple Heart indicator is YES AND the current purple heart
     * status is equal to Confirmed AND It is not true that the previous purple
     * heart status is equal to Confirmed AND the current enrollment priority is
     * equal to PG3 AND the previous enrollment priority is equal to PG4 OR PG5
     * OR PG6 OR PG7 OR PG8 THEN Trigger the mailing of the 630D letter
     */
    public void testTrigger_630D() throws Exception {
        //Person onFile = this.buildSimplePerson();
        PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(new BigDecimal("401"));        
        Person onFile = this.getPersonService().getPerson(personKey);              
//        this.attachVerifiedEnrollment(onFile);
//        this.setEnrollmentStatus(EnrollmentStatus.CODE_PENDING_PURPLE_HEART_UNCONFIRMED.getCode(), onFile);
//        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);
//        this.attachPurpleHeartWithPHStatusPending(onFile);
        Person incoming = this.savePerson(onFile);
//        this.setPurpleHeartStatus(DecorationStatus.CODE_CONFIRMED,
//                incoming);
        PurpleHeart purpleHeart = new PurpleHeart();
        purpleHeart.setPhIndicator(Boolean.TRUE);
        this.getMergeRuleService().mergePurpleHeart(purpleHeart, incoming.getPurpleHeart());
//        incoming.addDecoration(purpleHeart);
        this.setPurpleHeartStatus(DecorationStatus.CODE_CONFIRMED, incoming);        
        this.setEnrollmentStatus(EnrollmentStatus.CODE_VERIFIED.getCode(), incoming);
        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_3);

        doTriggerLetter(incoming);

    }

    public void test630H() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachPurpleHeartWithPHStatusPending(onFile);
        this.attachVerifiedEnrollment(onFile);
        this.setEnrollmentStatus(EnrollmentStatus.CODE_VERIFIED.getCode(), onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_1);
        Person incoming = this.savePerson(onFile);
        DecorationStatus ds = this.getLookupService().getDecorationStatusByCode(DecorationStatus.CODE_CONFIRMED.getName());
        ((PurpleHeart)incoming.getDecorations().iterator().next()).setStatus(ds);
        doTriggerLetter(incoming);        
    }
    
    
    /*
     * public void testTrigger_604A() throws Exception {
     * incomingPerson.setUserEnrolleeValidThrough(new Integer(2007));
     * this.attachMeansTestWithMtCopayRequired(incomingPerson, new
     * BigDecimal(100),new BigDecimal(100));
     * this.doVerifiedTests(incomingPerson, EnrollmentPriorityGroup.GROUP_8); }
     * public void testTrigger_604B() throws Exception { Person onFile =
     * this.buildSimplePerson(); onFile.setUserEnrolleeValidThrough(null);
     * onFile.setEnrollmentDetermination(this.createEnrollmentDetermination());
     * onFile.getEnrollmentDetermination().setEgtSetting(this.getEgtService().getCurrentEGTSetting());
     * this.setEnrollmentStatus(EnrollmentStatus.CODE_VERIFIED.getName(),
     * onFile); Person incoming = this.getPersonService().save(onFile);
     * incoming.setUserEnrolleeValidThrough(new Integer(2007));
     * this.attachMeansTestWithGmtCopayRequired(incoming,new BigDecimal(100),new
     * BigDecimal(100)); this.setEnrollmentPriority(incoming,
     * EnrollmentPriorityGroup.GROUP_4); doTriggerLetter(incoming); }
     * 
     * public void testTrigger_630D() throws Exception { // run
     * testCreatePHPerson to get an id PersonIdEntityKeyImpl personKey = new
     * PersonIdEntityKeyImpl(new BigDecimal("263059"));
     * this.run630Test(personKey, EnrollmentPriorityGroup.GROUP_3); }
     * 
     * public void testTrigger_630G() throws Exception { //263094
     * PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(new
     * BigDecimal("263094")); this.run630Test(personKey,
     * EnrollmentPriorityGroup.GROUP_2); }
     * 
     * public void testTrigger_630H() throws Exception { PersonIdEntityKeyImpl
     * personKey = new PersonIdEntityKeyImpl(new BigDecimal("263109"));
     * this.run630Test(personKey, EnrollmentPriorityGroup.GROUP_1); }
     * 
     */
    
    public void create640BPerson() throws Exception {

        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEligibilityStatusToVerified(onFile);
        this.attachMeansTestWithMtCopayRequired(onFile, new BigDecimal(1), new BigDecimal(2));
        this.attachCatastrophicDisability(onFile);
        Person incoming = this.savePerson(onFile);
        this.getEligibilityEnrollmentService().updateEligibilityData(incoming);
        this.setComplete();
        System.out.println("Person id="
                + incoming.getPersonEntityKey().getKeyValueAsString());        
    }
    
    public void create640BPersonWithNullPriority() throws Exception {

        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEligibilityStatusToVerified(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);
        Person incoming = this.savePerson(onFile);
        this.getEligibilityEnrollmentService().updateEligibilityData(incoming);
        this.setComplete();
        System.out.println("Person id="
                + incoming.getPersonEntityKey().getKeyValueAsString());        
    }
    
    public void create640BPersonWithNullPriorityAndExistingCD() throws Exception {

        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile);
        this.setEligibilityStatusToVerified(onFile);
        this.setEnrollmentPriority(onFile, EnrollmentPriorityGroup.GROUP_8);
        this.attachCatastrophicDisability(onFile);        
        Person incoming = this.savePerson(onFile);
        this.getEligibilityEnrollmentService().updateEligibilityData(incoming);
        this.setComplete();
        System.out.println("Person id="
                + incoming.getPersonEntityKey().getKeyValueAsString());        
    }        
    
    public void update640BPerson_2() throws Exception {

        PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(new BigDecimal("20722788"));        
        Person incoming = this.getPersonService().getPerson(personKey);        
        this.attachCatastrophicDisability(incoming);
        this.savePerson(incoming);
        this.setComplete();
        System.out.println("Person id="
                + incoming.getPersonEntityKey().getKeyValueAsString());        
    }
    
    public void update640BPerson_3() throws Exception {

        // PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(new BigDecimal("20722418"));        
         //Person incoming = this.getPersonService().getPerson(personKey);        
         Person incoming = this.getPerson("20722788");
         incoming.getEligibilityVerification().setVerificationMethod("testhfghfgh");
         this.getEligibilityEnrollmentService().updateEligibilityData(incoming);
         this.setComplete();
         System.out.println("Person id="
                 + incoming.getPersonEntityKey().getKeyValueAsString());        
     }    
    
    public void update640BPerson_1() throws Exception {

        // PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(new BigDecimal("20722418"));        
         //Person incoming = this.getPersonService().getPerson(personKey);        
         Person incoming = this.getPerson("20722418");
         this.attachCatastrophicDisability(incoming);
         this.getEligibilityEnrollmentService().updateEligibilityData(incoming);
         this.setComplete();
         System.out.println("Person id="
                 + incoming.getPersonEntityKey().getKeyValueAsString());        
     }            
 
    
    //94429
    public void testTrigger_640B_nullPriority() throws Exception {
        Person incoming = this.getPerson("148622");
        this.attachCatastrophicDisability(incoming);
        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_4);
        this.setEnrollmentStatus(EnrollmentStatus.CODE_VERIFIED.getCode(), incoming);
        doTriggerLetter(incoming);
    }
    
    public void testTrigger_640B_nullPriorityWithExistingCD() throws Exception {
        Person incoming = this.getPerson("148643");
        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_4);
        this.setEnrollmentStatus(EnrollmentStatus.CODE_VERIFIED.getCode(), incoming);
        doTriggerLetter(incoming);
    }        

    public void testTrigger_640B_Neg() throws Exception {
        Person onFile = this.buildSimplePerson();
        this.attachVerifiedEnrollment(onFile); //will not be found be query so effectively null priority
        Person incoming = this.savePerson(onFile);
        this.attachCatastrophicDisability(incoming);        
        this.setEnrollmentPriority(incoming, EnrollmentPriorityGroup.GROUP_4);

        doTriggerLetter(incoming);
    }    
}
