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

// Java classes

// Library classes

// Framework classes

import java.math.BigDecimal;
import java.util.Date;

import gov.va.med.fw.validation.ValidationMessages;

// ESR classes
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.person.Association;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.lookup.AssociationType;
import gov.va.med.esr.common.model.lookup.ComLetterTemplateType;
import gov.va.med.esr.common.model.lookup.ComMailingStatusType;
import gov.va.med.esr.common.model.lookup.EligibilityType;
import gov.va.med.esr.common.model.lookup.Gender;
import gov.va.med.esr.common.model.comms.CommsLogEntry;
import gov.va.med.esr.common.model.ee.Eligibility;
import gov.va.med.esr.common.persistent.comms.CommsLogEntryDAO;
import gov.va.med.esr.service.trigger.LetterTrigger;
import gov.va.med.esr.common.util.RuleAbstractTestCase;


/**
 * 
 * @author Carlos Ruiz
 * @version 1.0
 */
public class LetterMailingValidationTest extends RuleAbstractTestCase {
    private CommsLogEntryDAO commsLogEntryDAO = null;
    
    public LetterMailingValidationTest(String testName) {
        super(testName);
        // TODO Auto-generated constructor stub
    }
    

    public void testLetterMailing_601B_POA() throws Exception {
        Person onFile = this.createTestPerson();
        this.attachPrimaryMeansTest(onFile);
        onFile.addAddress(this.createAddress());
        Person incoming = this.getPersonService().save(onFile);
        CommsLogEntry CommEntry = this.createCommsLogEntry(incoming, LetterTrigger.DataType.FORM_NUMBER_601B.getName());        
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(CommEntry, incoming);
        assertTrue(vm.getCount() == 0);    }
    
    public void testLetterMailing_600C() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_600C.getName());
    }
    public void testLetterMailing_400() throws Exception {
        Person onFile = this.createTestPerson();
        this.attachMeansTestWithMtCopayExempt(onFile);
        this.setEligibilityStatusToVerified(onFile);
        this.attachVerifiedEnrollment(onFile);
        this.attachPurpleHeartWithPHStatusPending(onFile);
        Eligibility e = new Eligibility();
        e.setPrimary();
        e.setType(getLookupService().getEligibilityTypeByCode(EligibilityType.PURPLE_HEART_RECIPIENT.getCode()));
        onFile.getEnrollmentDetermination().setPrimaryEligiblity(e);        
        Person incoming = this.getPersonService().save(onFile);

        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, ComLetterTemplateType.FORM_NUMBER_400.getCode());       
        this.getCommsLogEntryDAO().insert(commEntry);    
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
        assertTrue(vm.getCount() == 0);                
    }    
    
	public void testLetterMailing_683A_no_nok() throws Exception {

		// Notice that did not attach a NOK
		Person onFile = this.createTestPerson();
		onFile.addSsn(this.createSSN());		
		this.attachVerifiedEnrollment(onFile);
		Eligibility e = new Eligibility();
		this.setEligibilityStatusToVerified(onFile);		
		e.setPrimary();
		e.setType(getLookupService().getEligibilityTypeByCode(EligibilityType.NSC.getCode()));
		onFile.getEnrollmentDetermination().setPrimaryEligiblity(e);
		this.attachMeansTestWithMtCopayRequired(onFile, new BigDecimal(3), new BigDecimal(3));
		this.getPersonHelperService().getCurrentIncomeTest(onFile).setHardship(this.createHardship("test"));
		Person incoming = savePerson(onFile);

        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, ComLetterTemplateType.FORM_NUMBER_683A.getCode());       
        this.getCommsLogEntryDAO().insert(commEntry);    
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
        assertTrue(vm.getCount() == 1);  
	}
	public void testLetterMailing_683A_with_nok() throws Exception {

		// Notice that did not attach a NOK
		Person onFile = this.createTestPerson();
		onFile.addSsn(this.createSSN());
		this.attachNextOfKin(onFile);
		this.attachVerifiedEnrollment(onFile);
		Eligibility e = new Eligibility();
		this.setEligibilityStatusToVerified(onFile);		
		e.setPrimary();
		e.setType(getLookupService().getEligibilityTypeByCode(EligibilityType.NSC.getCode()));
		onFile.getEnrollmentDetermination().setPrimaryEligiblity(e);
		this.attachMeansTestWithMtCopayRequired(onFile, new BigDecimal(3), new BigDecimal(3));
		this.getPersonHelperService().getCurrentIncomeTest(onFile).setHardship(this.createHardship("test"));
		Person incoming = savePerson(onFile);

        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, ComLetterTemplateType.FORM_NUMBER_683A.getCode());       
        this.getCommsLogEntryDAO().insert(commEntry);    
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
        assertTrue(vm.getCount() == 0);  
	}
	
	public void testLetterMailing_450() throws Exception {

		Person onFile = this.createTestPerson();
		onFile.addSsn(this.createSSN());
		this.attachVerifiedEnrollment(onFile);
		Eligibility e = new Eligibility();
		this.setEligibilityStatusToVerified(onFile);		
		e.setPrimary();
		e.setType(getLookupService().getEligibilityTypeByCode(EligibilityType.NSC.getCode()));
		onFile.getEnrollmentDetermination().setPrimaryEligiblity(e);

		Person incoming = savePerson(onFile);

        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, ComLetterTemplateType.FORM_NUMBER_450.getCode());
        commEntry.setIvmCaseClosureDate(new Date());
        commEntry.setIvmCaseNumber("SDFSDF");
        this.getCommsLogEntryDAO().insert(commEntry);    
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
        assertTrue(vm.getCount() == 0);  
	}			  		
    
	private void attachNextOfKin(Person person) throws Exception {
	    Association nok = this.createAssociation("none", "brother");
        nok.getRepresentativeName().setPrefix(null);
        nok.getRepresentativeName().setMiddleName("nokMiddleName");
        nok.setType(this.getLookupService().getAssociationTypeByCode(AssociationType.CODE_PRIMARY_NEXT_OF_KIN.getCode()));
        person.addAssociation(nok);		
	}
	
    public void testLetterMailing_600D() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_600D.getName());
    }
    
    public void testLetterMailing_620A() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_620A.getName());
    }
    
    public void testLetterMailing_623D() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_623D.getName());
    }
    
    public void testLetterMailing_630A() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_630A.getName());
    }           
    
    public void testLetterMailing_630B() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_630B.getName());
    }               
    
    public void testLetterMailing_630C() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_630C.getName());
    }               
    
    public void testLetterMailing_630G() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_630G.getName());
    }               
    
    public void testLetterMailing_630H() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_630H.getName());
    }               
    
    public void testLetterMailing_640D() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_640D.getName());
    }               
    
    public void testLetterMailing_640F() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_640F.getName());
    }                  
    
    public void testLetterMailing_640G() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_640G.getName());
    }                  
    
    public void testLetterMailing_640H() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_640H.getName());
    }                  
    
    public void testLetterMailing_640I() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_640I.getName());
    }
    
    public void testLetterMailing_640V() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_640V.getName());
    }                  
    
    public void testLetterMailing_640V_Neg() throws Exception {
        runNegTest(LetterTrigger.DataType.FORM_NUMBER_640V.getName());
    }    
    
    public void testLetterMailing_293() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_293.getName());
    }                  
    
    public void testLetterMailing_600D_Neg() throws Exception {
        runNegTest(LetterTrigger.DataType.FORM_NUMBER_600D.getName());
    }        
    
    public void testLetterMailing_400H() throws Exception {
        runTestForVerifiedPerson(LetterTrigger.DataType.FORM_NUMBER_400H.getName());
    }       
    
    private void runTestForVerifiedPerson(String form) throws Exception {
        Person onFile = this.createTestPerson();
        this.attachMeansTestWithMtCopayExempt(onFile);
        this.setEligibilityStatusToVerified(onFile);
        this.attachVerifiedEnrollment(onFile);
        Person incoming = this.getPersonService().save(onFile);
        this.setServiceConnectedPercentage(new Integer(60), incoming);        
        this.getEligibilityEnrollmentService().updateEligibilityData(incoming);
        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, form);
        this.getCommsLogEntryDAO().insert(commEntry);    
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
        assertTrue(vm.getCount() == 0);        
    }
    
    private void runNegTest(String form) throws Exception {
        Person onFile = this.createTestPerson();
        this.attachMeansTestWithMtCopayExempt(onFile);
        this.setEligibilityStatusToVerified(onFile);
        this.setServiceConnectedPercentage(new Integer(60), onFile);
        Person incoming = this.getPersonService().save(onFile);        
        this.getEligibilityEnrollmentService().assessEEImpact(incoming);
        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, form);
        commEntry.getAddress().setType(null);
        this.getCommsLogEntryDAO().insert(commEntry);    
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
        assertTrue(vm.getCount() == 1);        
    }    
    
    public void testLetterMailing_640B() throws Exception {
        Person onFile = this.createTestPerson();
        this.attachMeansTestWithMtCopayExempt(onFile);
        this.setEligibilityStatusToVerified(onFile);
        this.setServiceConnectedPercentage(new Integer(60), onFile);
        Person incoming = this.getPersonService().save(onFile);        
        this.getEligibilityEnrollmentService().assessEEImpact(incoming);
        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, LetterTrigger.DataType.FORM_NUMBER_640B.getName());
        this.getCommsLogEntryDAO().insert(commEntry);    
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
        assertTrue(vm.getCount() == 0);
    }
    
    public void testLetterMailing_640B_Neg() throws Exception {
        Person onFile = this.createTestPerson();
        Person incoming = this.getPersonService().save(onFile);        
        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, LetterTrigger.DataType.FORM_NUMBER_640B.getName());
        this.getCommsLogEntryDAO().insert(commEntry);    
        ValidationMessages vm = this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
        assertTrue(vm.getCount() != 0);
    }    
    
    public void testLetterMailing_601B() throws Exception {
        ValidationMessages vm = this.doValidation( LetterTrigger.DataType.FORM_NUMBER_601B.getName());
        assertTrue(vm.getCount() == 0);
    }
    
    public void testLetterMailing_604A() throws Exception {
        ValidationMessages vm = this.doValidation( LetterTrigger.DataType.FORM_NUMBER_604A.getName());
        assertTrue(vm.getCount() == 0);
    }
    
    public void testLetterMailing_604B() throws Exception {
        ValidationMessages vm = this.doValidation( LetterTrigger.DataType.FORM_NUMBER_604B.getName());
        assertTrue(vm.getCount() == 0);
    }
    
    public void testLetterMailing_623A() throws Exception {
        ValidationMessages vm = this.doValidation( LetterTrigger.DataType.FORM_NUMBER_623A.getName());
        assertTrue(vm.getCount() == 0);
    }       
    
    public void testLetterMailing_630D() throws Exception {
        ValidationMessages vm = this.doValidation( LetterTrigger.DataType.FORM_NUMBER_630D.getName());
        assertTrue(vm.getCount() == 0);
    }           

    public void testLetterMailing_640C() throws Exception {
        ValidationMessages vm = this.doValidation( LetterTrigger.DataType.FORM_NUMBER_640C.getName());
        assertTrue(vm.getCount() == 0);
    }
    
    public void testLetterMailing_290series() throws Exception {
        ValidationMessages vm = this.do290SeriesValidation( ComLetterTemplateType.FORM_NUMBER_290, false);
        assertTrue(vm.getCount() == 0);
        
        vm = this.do290SeriesValidation( ComLetterTemplateType.FORM_NUMBER_290, true);
        assertTrue(vm.getCount() == 1);
        
        vm = this.do290SeriesValidation( ComLetterTemplateType.FORM_NUMBER_291, false);
        assertTrue(vm.getCount() == 0);        
        
        vm = this.do290SeriesValidation( ComLetterTemplateType.FORM_NUMBER_292, true);
        assertTrue(vm.getCount() == 0);
        
        vm = this.do290SeriesValidation( ComLetterTemplateType.FORM_NUMBER_293, true);
        assertTrue(vm.getCount() == 0);               
    }               
    
    
    private ValidationMessages do290SeriesValidation(ComLetterTemplateType.Code form, boolean omitSSN) throws Exception {
        Person onFile = this.createTestPerson();
        this.attachVerifiedEnrollment(onFile);
        if (!omitSSN) onFile.addSsn(this.createSSN());
        Person incoming = this.getPersonService().save(onFile);
        this.setEligibilityStatusToVerified(incoming);
        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, form.getCode());
        this.getCommsLogEntryDAO().insert(commEntry);    
        return this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
    }    
    
    private ValidationMessages doValidation(String form) throws Exception {
        Person onFile = this.createTestPerson();
        this.attachMeansTestWithMtCopayExempt(onFile);     
        this.setEligibilityStatusToPendingVerification(onFile);
        Person incoming = savePerson(onFile);
        this.setEligibilityStatusToVerified(incoming);
        this.calculate(incoming);
        CommsLogEntry commEntry = this.createCommsLogEntry(incoming, form);
        this.getCommsLogEntryDAO().insert(commEntry);    
        return this.getRuleValidationService().validateLetterMailing(commEntry, incoming);
    }
    protected Person createTestPerson() throws Exception {
        Person onFile = this.buildSimplePerson();
        Address address = this.createAddress();
        onFile.addAddress(address);

        return onFile;        
    }    
    
    /**
     * @return Returns the commsLogEntryDAO.
     */
    public CommsLogEntryDAO getCommsLogEntryDAO() {
        return commsLogEntryDAO;
    }

    /**
     * @param commsLogEntryDAO The commsLogEntryDAO to set.
     */
    public void setCommsLogEntryDAO(CommsLogEntryDAO commsLogEntryDAO) {
        this.commsLogEntryDAO = commsLogEntryDAO;
    }    
}
