/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
// Package
package gov.va.med.esr.common.rule.service;

// Java classes
import java.util.Calendar;

// Library classes
import org.apache.commons.lang.Validate;

// ESR classes
import gov.va.med.esr.service.UnknownLookupCodeException;
import gov.va.med.esr.common.model.ee.EligibilityVerification;
import gov.va.med.esr.common.model.ee.ServiceConnectionAward;
import gov.va.med.esr.common.model.ee.VerificationInfo;
import gov.va.med.esr.common.model.financials.Income;
import gov.va.med.esr.common.model.lookup.AACIndicator;
import gov.va.med.esr.common.model.lookup.Disability;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.util.RuleAbstractTestCase;
import gov.va.med.esr.common.infra.ImpreciseDate;

/**
 * ProcessVBAFromZ07Test created on Aug 21, 2006
 * @author DNS   LEV
 */
public class ProcessVBAForZ11Test extends RuleAbstractTestCase {

   private static Person onfile = null;
   
	/**
	 * A default constructor
	 * @param testName
	 */
	public ProcessVBAForZ11Test(String testName) throws Exception {
		super(testName);
	}
   
   public void testIsDateOfDeath() throws Exception {
      
      // Simulate an incoming person
      Person incoming = (Person)onfile.clone();
      
      // Simulate an updated person. An updated person is 
      // a person that has been updated in other rule flows.
      // For this rule, there is no need to call other rule flows
      // to update an incoming person.
      Person updated = (Person)onfile.clone();
      
      try {
         // No error case for ORUZ11
         VerificationInfo info = new VerificationInfo("0L", "ORUZ11-E", null);
         info.setUnsolicitedType("VBA");
         
         // Populate incoming vet with date of death
         incoming.setDeathRecord( this.createDeathRecord() );
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
         
         // No error case for ORUZ11-HINQ
         info.setUnsolicitedType("HINQ");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
      }
      catch( Exception e ) {
         if( logger.isDebugEnabled() ) {
            logger.debug( "Got an un-expected validation exception ", e );
         }
         this.fail( "Got an un-expected validation exception", e );
      }
      
      // Reset incoming person
      incoming.setDeathRecord( null );
   }
   /**
    * test the requirement 646. If the onfile eligibiity status is 
    * verified , set the VBA Query Status to VBA Rejected.
    * @throws Exception
    */
   public void testReq646() throws Exception {
       

       // Simulate an incoming person
       
       setEligibilityStatusToVerified(onfile);
       setAACIndicator(AACIndicator.CODE_AAC_QUERIED_NO_DATA.getName(), onfile);
       onfile.setVeteran(Boolean.TRUE);
       
       Person incoming = (Person)onfile.clone();
       
       // Simulate an updated person. An updated person is 
       // a person that has been updated in other rule flows.
       // For this rule, there is no need to call other rule flows
       // to update an incoming person.
       Person updated = (Person)onfile.clone();
       
       try {
           
           
          // No error case for ORUZ11
          VerificationInfo info = new VerificationInfo("0L", "ORFZ11-E", null);
          info.setUnsolicitedType("VBA");
          
          // Populate incoming vet with date of death
          //incoming.setDeathRecord( this.createDeathRecord() );
          
          // Invoke ProcessVBAFromMVR rule flow
          this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
          
          assertTrue( "AAC Indicator must be VBA rejected", 
                   updated.getEligibilityVerification().getAacIndicator().getCode().equals(AACIndicator.CODE_DATA_REJECTED.getCode()));
       }
       catch( Exception e ) {
          if( logger.isDebugEnabled() ) {
             logger.debug( "Got an un-expected validation exception ", e );
          }
          this.fail( "Got an un-expected validation exception", e );
       }
    }
   
   public void testIsNoDataOnFile() throws Exception {
      
      // Simulate an incoming person
      Person incoming = (Person)onfile.clone();
      
      // Simulate an updated person. An updated person is 
      // a person that has been updated in other rule flows.
      // For this rule, there is no need to call other rule flows
      // to update an incoming person.
      Person updated = (Person)onfile.clone();
      
      try {
         // No error case for ORUZ11
         VerificationInfo info = new VerificationInfo("0L", "ORUZ11-E", "No Data on File");
         info.setUnsolicitedType("VBA");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
         
         // No error case for ORUZ11-HINQ
         info.setUnsolicitedType("HINQ");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
      }
      catch( Exception e ) {
         if( logger.isDebugEnabled() ) {
            logger.debug( "Got an un-expected validation exception ", e );
         }
         this.fail( "Got an un-expected validation exception", e );
      }
   }
   
   public void testIsEntitlementCodeInvalid() throws Exception {
      
      // Simulate an incoming person
      Person incoming = (Person)onfile.clone();
      
      // Simulate an updated person. An updated person is 
      // a person that has been updated in other rule flows.
      // For this rule, there is no need to call other rule flows
      // to update an incoming person.
      Person updated = (Person)onfile.clone();
      
      try {
         // No error case for ORUZ11
         VerificationInfo info = new VerificationInfo("09", "ORUZ11-E", "Entitlement Code invalid");
         info.setUnsolicitedType("VBA");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
         
         // No error case for ORUZ11-HINQ
         info.setUnsolicitedType("HINQ");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
      }
      catch( Exception e ) {
         if( logger.isDebugEnabled() ) {
            logger.debug( "Got an un-expected validation exception ", e );
         }
         this.fail( "Got an un-expected validation exception", e );
      }
   }
   
   public void testIsEntitlementCode01() throws Exception {
      
      // Simulate an incoming person
      Person incoming = (Person)onfile.clone();
      
      // Simulate an updated person. An updated person is 
      // a person that has been updated in other rule flows.
      // For this rule, there is no need to call other rule flows
      // to update an incoming person.
      Person updated = (Person)onfile.clone();
      
      try {
         // Set a service connection award to null
         incoming.setServiceConnectionAward( null );
         
         // No error case for ORUZ11
         VerificationInfo info = new VerificationInfo("01", "ORUZ11-E", "Entitlement Code invalid");
         info.setUnsolicitedType("VBA");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
         
         // No error case for ORUZ11-HINQ
         info.setUnsolicitedType("HINQ");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
      }
      catch( Exception e ) {
         if( logger.isDebugEnabled() ) {
            logger.debug( "Got an un-expected validation exception ", e );
         }
         this.fail( "Got an un-expected validation exception", e );
      }
   }
   
   public void testHasInvalidDisabilityCode() throws Exception {
      
      // Simulate an incoming person
      Person incoming = (Person)onfile.clone();
      
      // Simulate an updated person. An updated person is 
      // a person that has been updated in other rule flows.
      // For this rule, there is no need to call other rule flows
      // to update an incoming person.
      Person updated = (Person)onfile.clone();
      
      try {
         // Set service connection 
         ServiceConnectionAward sca = this.attachServiceConnectionAward( incoming );
         sca.addRatedDisability( this.createRatedDisability() );
         
         // No error case for ORUZ11
         VerificationInfo info = new VerificationInfo("01", "ORUZ11-E", "Entitlement Code invalid");
         info.setUnsolicitedType("VBA");
         
         // Set an exception for an unknown rated disability code
         info.addException( new UnknownLookupCodeException("Unknown", "123", Disability.class ) );
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
         
         // No error case for ORUZ11-HINQ
         info.setUnsolicitedType("HINQ");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
      }
      catch( Exception e ) {
         if( logger.isDebugEnabled() ) {
            logger.debug( "Got an un-expected validation exception ", e );
         }
         this.fail( "Got an un-expected validation exception", e );
      }
      
      // remove service connection award
      incoming.setServiceConnectionAward( null );
   }
   
   public void testIsEntitlementCodeValidForORUZ11() throws Exception {

      // Simulate an incoming person
      Person incoming = (Person)onfile.clone();
      
      // Simulate an updated person. An updated person is 
      // a person that has been updated in other rule flows.
      // For this rule, there is no need to call other rule flows
      // to update an incoming person.
      Person updated = (Person)onfile.clone();
      
      try {
         ServiceConnectionAward sca = this.attachServiceConnectionAward( incoming );
         
         Calendar calendar = Calendar.getInstance();
         calendar.roll( Calendar.YEAR, true );
         sca.setCombinedServiceConnectedPercentageEffectiveDate( new ImpreciseDate( calendar.getTime() ) );
         
         // No error case for ORUZ11
         VerificationInfo info = new VerificationInfo( "01", "ORUZ11-E", null );
         info.setUnsolicitedType("VBA");
         
         // Invoke ProcessVBAFromMVR rule flow
         this.getProcessVBARuleService().verifyEligibility( incoming, updated, info );
         
         // Check if the trigger enrollment process is set to false
         assertTrue( "Enrollment process must not be trigger", !info.isTriggerEnrollmentProcess() );
         
      }
      catch( Exception e ) {
         if( logger.isDebugEnabled() ) {
            logger.debug( "Got an un-expected validation exception ", e );
         }
         this.fail( "Got an un-expected validation exception", e );
      }
   }
   
	/**
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		super.afterPropertiesSet();
		Validate.notNull( this.getProcessVBARuleService(), "A process vba rule service is required" );
	}
   
   /**
    * @see gov.va.med.fw.util.AbstractTestCase#customSetUp()
    */
   protected void customSetUp() throws Exception {
      super.customSetUp();

      if( onfile == null ) {
         // Create a simple person without an enrollment
         // determination record.  This means that this is 
         // not an enrolled veteran.
         onfile = this.buildSimplePerson();
         this.getPersonService().save( onfile );
      }
   }
}