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

import gov.va.med.esr.common.clock.Clock;
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.common.model.comms.AacLetterRequest;
import gov.va.med.esr.common.model.ee.EGTSetting;
import gov.va.med.esr.common.model.ee.VerificationInfo;
import gov.va.med.esr.common.model.ee.EligibilityVerification;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.lookup.EligibilityStatus;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.person.BirthRecord;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.rule.data.BaseData;
import gov.va.med.esr.common.rule.data.CommsInputData;
import gov.va.med.esr.common.rule.data.EEInputData;
import gov.va.med.esr.common.rule.data.EventInputData;
import gov.va.med.esr.common.rule.data.ExternalSystemsInputData;
import gov.va.med.esr.common.rule.data.MilitaryServiceInputData;
import gov.va.med.esr.common.rule.data.POWInputData;
import gov.va.med.esr.common.rule.data.PersonInputData;
import gov.va.med.esr.common.rule.data.SSNVerificationResponseInputData;
import gov.va.med.esr.common.rule.data.accessor.DemographicAccessor;
import gov.va.med.esr.common.rule.service.MergeRuleService;
import gov.va.med.esr.service.ApplicationInProcessService;
import gov.va.med.esr.service.ClinicalDeterminationService;
import gov.va.med.esr.service.CommsLogService;
import gov.va.med.esr.service.EGTService;
import gov.va.med.esr.service.EligibilityEnrollmentService;
import gov.va.med.esr.service.FinancialsService;
import gov.va.med.esr.service.HandBookService;
import gov.va.med.esr.service.LogTransmissionService;
import gov.va.med.esr.service.LookupService;
import gov.va.med.esr.service.MessagingService;
import gov.va.med.esr.service.PersonHelperService;
import gov.va.med.esr.service.PersonService;
import gov.va.med.esr.service.PurpleHeartService;
import gov.va.med.esr.service.RegistryService;
import gov.va.med.esr.service.RelaxationPercentageService;
import gov.va.med.esr.service.ScheduledTaskService;
import gov.va.med.esr.service.SystemParameterService;
import gov.va.med.esr.service.VOAApplicationService;
import gov.va.med.esr.service.WorkflowService;
import gov.va.med.fw.model.AbstractEntity;
import gov.va.med.fw.model.AbstractKeyedEntity;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.model.lookup.Lookup;
import gov.va.med.fw.rule.AbstractRuleParameter;
import gov.va.med.fw.rule.RuleDataAware;
import gov.va.med.fw.rule.RuleException;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.transaction.TransactionTimestampManager;
import gov.va.med.fw.util.DateUtils;
import gov.va.med.fw.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.Validate;

/**
 * Project: Common
 * 
 * @author DNS   LEV
 * @version 1.0
 */
public abstract class BaseParameter extends AbstractRuleParameter {

    private static final long serialVersionUID = -1370346746640850300L;
    public static final String YES_INDICATOR = "Y";

   public static final String NO_INDICATOR = "N";

   public static final String[] invalidSSN = { "000000000", "111111111", "222222222",
         "333333333", "444444444", "555555555", "666666666", "777777777", "888888888",
         "999999999", "123456789" };
   
   private SystemParameterService systemParameterService = null;
   
   private PersonHelperService helperService = null;

   private MergeRuleService mergeRuleService = null;

   private LookupService lookupService = null;

   private MessagingService messagingService = null;
   
   private RelaxationPercentageService relaxationPercentageService = null;
   
   private ApplicationInProcessService applicationInProcessService = null;   
   
   private VOAApplicationService voaApplicationService = null;
   
   private String clinicalDeterminationServiceName = null;

   private String timestampManagerName = null;

   private String eligibilityEnrollmentServiceName = null;

   private String financialsServiceName = null;

   private String egtServiceName = null;

   private String purpleHeartServiceName = null;

   private String ScheduledTaskServiceName = null;
   
   private String commsLogServiceName = null;
   
   // 3.6 CCR 10960 
   private String handBookServiceName = null;
   
   private WorkflowService workflowService = null;

   private String esrImplementationDateString = null;

   private Person verifiedSiteData = null;
   
   private Person verifiedAapData = null;
   
   private Person unverifiedSiteData = null;
   
   private Person mostRecentSiteData = null;
   
   private String registryServiceName = null;
   
   private LogTransmissionService logMessagingService;
   
   protected BaseParameter() {
      super();
   }

   public String getUseCaseName() {
       BaseData data = this.getBaseData();
       return ( data != null ) ? data.getUseCaseName() : null;
   }

   public boolean isDatePrecise(Date input) {
      // If goes to this method, then date was precise.
      return true;
   }

   public boolean isDatePrecise(ImpreciseDate input) {
      // If goes to this method, then need to check if date
      // has precise format.
      if( input != null ) {
         if( input.isPrecise() ) {
            return true;
         }
         else {
            if( !input.isMonthPrecise() ) {
               return false;
            }
         }
      }
      return true;
   }

   /**
    * Tests if incomingSite is a parent, or ancestor, to the satellite site. 
    * @param satellite
    * @param incomingSite
    * @return
    * @throws RuleException
    */
   public boolean isSatelliteSite(VAFacility satellite, VAFacility incomingSite) throws RuleException {
       // Only need to check one direction. Sending sites are not satellites.
	   try {
	       if (satellite != null && incomingSite != null) {
	    	   BigDecimal childId = satellite.getIdentifier();
	           BigDecimal parentId = satellite.getParentId();
	           VAFacility parentFacility = null;
               /*
				* CCR9564 -- test for grand parent of satellite as well Income
				* test not uploading when Site Conducting Test is a child to
				* another child facility
				*/
	           
	           // also prevents cases where parentId = childId, causing infinite loops
	           while (parentId != null && !(parentId.compareTo(childId) == 0)) {
	        	   // test for parent of satellite site
	               if (parentId.compareTo(incomingSite.getIdentifier()) == 0) {
	            	   return true;
	               }
	               
	               // further go up the chain of parents until we exhaust the ancestor tree or find a match
	               parentFacility = this.getLookupService().getVAFacilityById(parentId);
	               childId = parentId;
	               parentId = (parentFacility==null ? null : parentFacility.getParentId());
	           }
	       }
	   }
 	   catch( ServiceException e ) {
 		   throw new RuleException("Failed to get VA Facility ", e);
	   }
 	   	
 	   return false;
   } 

   /**
	 * Find the parent (sending) site among the preferred facility or its parent/ancestors
	 * @param preferredFacility
	 * @return
	 * @throws ServiceException
	 */
   public VAFacility getParentSite(VAFacility preferredFacility)
	throws ServiceException {	
		if (preferredFacility == null)
			return null;

		VAFacility facility = preferredFacility;

		if (Boolean.TRUE.equals(facility.isMfnzegRecipient())) {
			return facility;
		}

       /**
        * there is no parent so. this must be parent.
        */
       if (facility.getParentId() == null ) {
             return facility;
       }

		// go up the parent tree until we exhaust the parent or find a sending site
		while (facility.getParentId() != null
				&& !(facility.getParentId().compareTo(facility.getIdentifier()) == 0)) {
			facility = this.getLookupService().getVAFacilityById(
					facility.getParentId());
			if (Boolean.TRUE.equals(facility.isMfnzegRecipient())) {
				return facility;
			}
		}
		// sending site of the preferred facility not found
		throw (new ServiceException("Parent sending site for facility "
				+ preferredFacility.getStationNumber() + " cannot be found"));
	}
  
   // Code CR 8672 - many issues, this one being that future check must
   // ignore time element
   public boolean isAfterIgnoreTime(Date date1, Date date2) {
       return DateUtils.isAfterIgnoreTime(date1, date2);
   }
   
   /**
    * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
    */
   public void afterPropertiesSet() throws Exception {
      super.afterPropertiesSet();
      Validate.notNull(helperService, "Helper service must be configured");
   }

   public EntityKey getEntityKey() {

      EntityKey key = null;
      AbstractEntity entity = this.getKeyedEntity();
      if( entity instanceof AbstractKeyedEntity ) {
         key = ( (AbstractKeyedEntity)entity ).getEntityKey();
      }
      return key;
   }

   /**
    * @return Returns the egtService.
    */
   public EGTService getEgtService() throws ServiceException {
      return (EGTService)this.getComponent(this.getEgtServiceName());
   }

   /**
    * Returns a person that is pristine from the database and it is not altered during a
    * rule flow execution's trasaction.
    * 
    * @return A person that is pristine from the database
    */
   public Person getPristinePerson() {
      return (Person)this.getPristineData();
   }

   /**
    * Returns a person that is built from incoming data
    * 
    * @return A person that comes in from VISTA or HEC
    */
   public Person getIncomingPerson() {
      return (Person)this.getIncomingData();
   }

   /**
    * Returns a person that is currently being updated in the rule flow's process
    * 
    * @return A person that is currently being updated
    */
   public Person getResultPerson() {
      return (Person)this.getResultData();
   }

   public VAFacility getSendingFacility() {
       
       BaseData data = this.getBaseData();
       return ( data != null ) ? data.getSendingFacility() : null;
   }

   public String getDfn() {
      BaseData data = this.getBaseData();
      return ( data != null ) ? data.getDfn() : null;
   }

   /**
    * @return Returns the aacInfo.
    */
   public VerificationInfo getAacInfo() {
      PersonInputData data = this.getPersonInputData();
      return ( data != null ) ? data.getVerificationInfo() : null;
   }

   /**
    * @see gov.va.med.esr.common.rule.PersonInput#isUpdateFromGUI()
    */
   public boolean isUpdateFromGUI() {
      if( this.getPersonInputData() == null ) {
         // get from base class
         return ( (BaseData)this.getRuleDataAware() ).isDataFromGUI();
      }
      return this.getPersonInputData().isUpdateFromGUI();
   }
   
   /**
    * @see gov.va.med.esr.common.rule.PersonInput#isUpdateFromGUI()
    */
   public boolean isUpdateFromMVI() {
      if( this.getPersonInputData() == null ) {
         // get from base class
         return ( (BaseData)this.getRuleDataAware() ).isDataFromMVI();
      }
      return this.getPersonInputData().isDataFromMVI();
   }

   public boolean isMsdsActive()throws RuleException {
	   try {
			return this.getSystemParameterService().getMSDSServiceIndicator()
					.booleanValue();
		} catch (ServiceException serviceEx) {
			throw new RuleException("Error getting systemParameterService",
					serviceEx);
		}
   }
   public boolean isFromAddNewPerson() {
	   BaseData bd = this.getBaseData();
	   return (bd != null) ? bd.isFromAddNewPerson() : false;
   }   
   public boolean isReconActive()throws RuleException {
	   try {
			return this.getSystemParameterService().getMSDSReconIndicator()
					.booleanValue();
		} catch (ServiceException serviceEx) {
			throw new RuleException("Error getting systemParameterService",
					serviceEx);
		}
   }
   
   public EEInputData getEEInputData() {
      RuleDataAware ruleDataAware = this.getRuleDataAware();
      if( ruleDataAware instanceof EEInputData ) {
         return (EEInputData)ruleDataAware;
      }
      return null;
   }

   public EventInputData getEventInputData() {
       RuleDataAware ruleDataAware = this.getRuleDataAware();
       if (ruleDataAware instanceof EventInputData) {
           return (EventInputData) ruleDataAware;
       }
       return null;
   }   
   
   public ExternalSystemsInputData getExternalSystemsInputData() {
      RuleDataAware ruleDataAware = this.getRuleDataAware();
      if( ruleDataAware instanceof ExternalSystemsInputData ) {
         return (ExternalSystemsInputData)ruleDataAware;
      }
      return null;
   }

   public IncomeTest getPrimaryTest() {
      return this.getHelperService().getCurrentIncomeTest(this.getIncomingPerson());
   }

   /**
    * Returns a person that is built from a verified site record. A site record is an
    * ORUZ07 received from a site and stored HL7_TRANSACTION_LOG table.
    * 
    * @return A person that represents a verified site record
    */
   public Person getVerifiedSiteData()  throws RuleException {
      if( this.verifiedSiteData == null ) {
         this.verifiedSiteData = this.getSiteData(EligibilityStatus.CODE_VERIFIED); 
      }
      return this.verifiedSiteData;
   }

   /**
    * Get the Verified AAP data from ADRAAP
    * 
    * @return
    * @throws RuleException
    */
   public Person getVerifiedAapData() throws RuleException {
	   if (this.verifiedAapData == null) {
		   try {

			   Person pristine = this.getPristinePerson();
			   String shortVPID = pristine.getVPIDEntityKey().getShortVPID(); 
			   List list = this.getApplicationInProcessService().getApplicationStatusesByIcn(shortVPID);
			   if (list == null || list.size() == 0 || list.size() > 1) {
				   return null;
			   }
			   Person aapPerson = this.getApplicationInProcessService().getCompletedPersonByIcn(shortVPID);
			   if (aapPerson != null) {
				   EligibilityVerification ev = aapPerson.getEligibilityVerification();
				   if (ev != null ) {
					   String code = ev.getEligibilityStatus() != null ? ev.getEligibilityStatus().getCode() : null;
					   if (EligibilityStatus.CODE_VERIFIED.getCode().equals(code)) {
						   this.verifiedAapData = aapPerson;
					   }
				   }
			   }
		   }
		   catch( ServiceException serviceEx ) {
			   throw new RuleException("Error getting Verified AAP Data", serviceEx);
		   }      
	   }
	   
	   return this.verifiedAapData;
   }
   
   /**
    * Returns a person that is built from a verified site record. A site record is an
    * ORUZ07 received from a site and stored HL7_TRANSACTION_LOG table.
    * 
    * @return A person that represents a verified site record
    */
   public Person getUnverifiedSiteData()  throws RuleException {
      if( unverifiedSiteData == null ) {
         unverifiedSiteData = this.getSiteData( EligibilityStatus.CODE_PENDING_VERIFICATION );
         if( unverifiedSiteData == null ) {
            unverifiedSiteData = this.getSiteData( EligibilityStatus.CODE_PENDING_REVERIFICATION );
         }
      }
      return unverifiedSiteData;
   }
   
   /**
    * @return
    * @throws RuleException
    */
   public Person getMostRecentSiteData() throws RuleException {
      if( mostRecentSiteData == null ) {
         mostRecentSiteData = this.getVerifiedSiteData();
         if( mostRecentSiteData == null ) {
            mostRecentSiteData = this.getUnverifiedSiteData();
         }
      }
      return mostRecentSiteData;
   }
   
   public CommsInputData getCommsInputData() {
      if( this.getRuleDataAware() instanceof CommsInputData ) {
         return (CommsInputData)this.getRuleDataAware();
      }
      return null;
   }

   public DemographicAccessor getDemographicAccessor() {
          if( this.getRuleDataAware() instanceof DemographicAccessor ) {
             return (DemographicAccessor)this.getRuleDataAware();
          }
          return null;
       }
   
   /**
    * @return Returns the firedClockType.
    */
   public Clock.Type getFiredClockType() {
       RuleDataAware data = this.getRuleDataAware();
       if( data instanceof BaseData ) {
           return ( (BaseData)data ).getFiredClockType();
       }
       return null;
   }

   public Date getClockStartDate(long days) {
      long msPerDay = 1000 * 60 * 60 * 24;
      long millis = msPerDay * days;
      return new Date(System.currentTimeMillis() + millis);
   }

   /**
    * Gets the current date from the transaction. If no transaction is started, it will
    * return the system date.
    * 
    * @return The transaction date.
    */
   public Date getCurrentDate() {
      try {
         return getTimestampManager().getTransactionTimestamp();
      }
      catch( Exception ex ) {
         throw new RuntimeException("Unable to get transaction timestamp.", ex);
      }
   }

   /**
    * 5.1 Invalid Values The first five digits of an SSN may not be zeros (00000). The
    * record for which this is true will not be accepted; however, an application error
    * (AE) should not be generated. If any of the following conditions is found to be true
    * for an SSN, the system will compute a pseudo SSN: 1. All digits of the SSN are the
    * same number (e.g., 111111111, 222222222, 333333333, etc.) 2. The first three digits
    * of the SSN are 000 3. The fourth and fifth digits of the SSN are 00 4. The last four
    * digits of the SSN are 0000 5. The digits of the SSN are 123456789
    */
   public boolean isSSNValid(String ssn) {
      if( StringUtils.isNotEmpty(ssn) ) {
         if( StringUtils.contains(invalidSSN, ssn)
               || StringUtils.equals("000", ssn.substring(0, 3))
               || StringUtils.equals("00", ssn.substring(3, 5))
               || StringUtils.equals("0000", ssn.substring(5, 9)) ) {
            return false;
         }
      }
      return true;
   }

   /**
    * @return Returns the ESR Implementation Date
    */
   public Date getEsrImplementationDate() throws RuleException {

      try {
          return this.getSystemParameterService().getEsrImplementationDate();
       }
       catch( ServiceException serviceEx ) {
          throw new RuleException("Error getting PurpleHeartService", serviceEx);
       }      
   }
   
   /**
    * @return Returns the Enrollment Regulation Date
    */
   public Date getEnrollmentRegulationDate() throws RuleException {

      try {
          return this.getSystemParameterService().getEnrollmentRegulationDate();
       }
       catch( ServiceException serviceEx ) {
          throw new RuleException("Error getting PurpleHeartService", serviceEx);
       }      
   }

   // CCR 8395
   public void setImprovedByMSDS(boolean improvedByMSDS) {
       if( this.getRuleDataAware() instanceof MilitaryServiceInputData ) {
           ((MilitaryServiceInputData)this.getRuleDataAware()).setImprovedByMSDS(improvedByMSDS);
       }
   }   
   
   protected PurpleHeartService getPurpleHeartService() throws RuleException {
      try {
         return (PurpleHeartService)this.getComponent(this.getPurpleHeartServiceName());
      }
      catch( ServiceException serviceEx ) {
         throw new RuleException("Error getting PurpleHeartService", serviceEx);
      }
   }
   
   protected CommsLogService getCommsLogService() throws RuleException {
       try {
          return (CommsLogService)this.getComponent(this.getCommsLogServiceName());
       }
       catch( ServiceException serviceEx ) {
          throw new RuleException("Error getting CommsLogService", serviceEx);
       }
    }   
   
   // 3.6 CCR 10960 
   protected HandBookService getHandBookService() throws RuleException {
       try {
          return (HandBookService)this.getComponent(this.getHandBookServiceName());
       }
       catch( ServiceException serviceEx ) {
          throw new RuleException("Error getting HandBookService", serviceEx);
       }
    }   

   protected ScheduledTaskService getScheduledTaskService() throws RuleException {
      try {
         return (ScheduledTaskService)this.getComponent(this
               .getScheduledTaskServiceName());
      }
      catch( ServiceException serviceEx ) {
         throw new RuleException("Error getting ScheduledTaskService", serviceEx);
      }
   }

   /**
    * @return
    */
   protected EGTSetting getActiveEGTSetting() {
      return this.getBaseData() != null ? this.getBaseData().getActiveEGTSetting() : null;
   }

   /**
    * @return
    * @throws RuleException
    */
   protected EGTSetting getCurrentEGTSetting() throws RuleException {
      // Check if egt is provided by the batch egt process
      EGTSetting egt = this.getActiveEGTSetting();
      // If not provided by batch, go get the active setting using service
      if( egt == null ) {
         try {
            egt = this.getEgtService().getCurrentEGTSetting();
         }
         catch( ServiceException e ) {
            throw new RuleException("Failed to get egt setting ", e);
         }
      }
      return egt;
   }

   /**
    * Commonly used method to get the DOB. Will return a default value for imprecise dates
    * when necessary.
    * 
    * @param person
    * @return
    */
   protected Date getDateOfBirth(Person person) {
      Date dateOfBirth = null;
      if( person != null ) {
         BirthRecord birthRecord = person.getBirthRecord();
         ImpreciseDate impreciseDate = ( birthRecord != null ) ? birthRecord
               .getBirthDate() : null;
         dateOfBirth = ( impreciseDate != null ) ? ImpreciseDateUtils
               .getDateWithDefault(impreciseDate) : null;
      }
      return dateOfBirth;
   }

   /**
    * @return
    * @throws RuleException
    */
   protected EligibilityEnrollmentService getEligibilityEnrollmentService()
         throws RuleException {
      try {
         return (EligibilityEnrollmentService)this.getComponent(this
               .getEligibilityEnrollmentServiceName());
      }
      catch( ServiceException serviceEx ) {
         throw new RuleException("Error getting EligibilityEnrollmentService", serviceEx);
      }
   }

   /**
    * @return
    */
   protected BaseData getBaseData() {
      RuleDataAware data = this.getRuleDataAware();
      if( data instanceof BaseData ) {
         return (BaseData)data;
      }
      return null;
   }

   /**
    * Returns the history person associated with the prior enrollment record. This person
    * is populated with several E&E objects such as POW, PH, and others.
    * 
    * @return
    * @throws RuleException
    */
   protected Person getPriorEEPerson() throws RuleException {
      Person person = this.getIncomingPerson();
      Validate.notNull(person, "A person must not be null ");

      try {
         return this.getEligibilityEnrollmentService().getPersonForPriorEnrollment(
               person.getEntityKey());
      }
      catch( ServiceException e ) {
         throw new RuleException("Failed to get prior person", e);
      }
   }

   /**
    * @return
    */
   protected POWInputData getPOWInputData() {
      if( this.getRuleDataAware() instanceof POWInputData ) {
         return ( (POWInputData)this.getRuleDataAware() );
      }
      return null;
   }

   protected AbstractKeyedEntity getKeyedEntity() {
      AbstractKeyedEntity key = null;
      AbstractEntity entity = this.getIncomingData();
      if( entity instanceof AbstractKeyedEntity ) {
         key = (AbstractKeyedEntity)entity;
      }
      return key;
   }

   /**
    * Return sorted list of changes events
    * 
    * @param dates
    * @return
    */
   protected List getSortedChangeEvents(Set events) {
      List sortedEvents = new ArrayList();
      if( events != null ) {
         sortedEvents.addAll(events);
         Collections.sort(sortedEvents);
      }
      return sortedEvents;
   }

   /**
    * Returns a person that is pristine from the database and it is not altered during a
    * rule flow execution's trasaction.
    * 
    * @return A person that is pristine from the database
    */
   protected Person getSiteData(EligibilityStatus.Code status) throws RuleException {
      Person verified = null;
      try {
         PersonInputData data = this.getPersonInputData();
         PersonService ps = data != null ? data.getPersonService() : null;
         if( ps != null ) {
            Person pristine = this.getPristinePerson();
            if( pristine != null ) {
               verified = ps.getPersonFromSiteData(pristine.getPersonEntityKey(), status
                     .getName());
            }
         }
      }
      catch( ServiceException e ) {
         throw new RuleException( "Failed to get a verified site data", e );
      }
      return verified;
   }

   protected ClinicalDeterminationService getClinicalDeterminationService()
         throws RuleException {
      try {
         return (ClinicalDeterminationService)this.getComponent(this
               .getClinicalDeterminationServiceName());
      }
      catch( ServiceException serviceEx ) {
         throw new RuleException("Error getting ClinicalDeterminationService", serviceEx);
      }
   }

   protected TransactionTimestampManager getTimestampManager() throws RuleException {
      try {
         return (TransactionTimestampManager)this.getComponent(this
               .getTimestampManagerName());
      }
      catch( ServiceException serviceEx ) {
         throw new RuleException("Error getting TransactionTimestampManager", serviceEx);
      }
   }

   protected FinancialsService getFinancialsService() throws RuleException {
      try {
         return (FinancialsService)this.getComponent(this.getFinancialsServiceName());
      }
      catch( ServiceException serviceEx ) {
         throw new RuleException("Error getting FinancialsService", serviceEx);
      }
   }

   /**
    * @return A rule data that encapsulated a person data
    */
   private PersonInputData getPersonInputData() {
      RuleDataAware ruleDataAware = this.getRuleDataAware();
      if( ruleDataAware instanceof PersonInputData ) {
         return (PersonInputData)ruleDataAware;
      }
      return null;
   }
   
   protected SSNVerificationResponseInputData getSSNVerificationResponseInputData() {
       RuleDataAware ruleDataAware = this.getRuleDataAware();
       if( ruleDataAware instanceof SSNVerificationResponseInputData) {
           return (SSNVerificationResponseInputData)ruleDataAware;
       }
       return null;
   }
   
   /**
    * Helper method to return lookup code.
    * @param lookup
    * @return null if lookup is null, otherwise lookup code
    */
   protected String getCode(Lookup lookup) {
       return lookup == null ? null : lookup.getCode();
   }
   
   protected String getSubject() {
       String subject = AacLetterRequest.VETERAN_LETTER; // default

       // Need to deal with different contexts here
       // Context 1
       SSNVerificationResponseInputData data = this
               .getSSNVerificationResponseInputData();
       if (data != null && data.getResultSSNVerificationData() != null) {
           if (data.getResultSSNVerificationData()
                   .isSsnVerificationForDependent()) {
               subject = AacLetterRequest.DEPENDENT_LETTER;
           } else if (data.getResultSSNVerificationData()
                   .isSsnVerificationForSpouse()) {
               subject = AacLetterRequest.SPOUSE_LETTER;
           } else {
               subject = AacLetterRequest.VETERAN_LETTER;
           }

       }
       // Context 2
       else if (getCommsInputData() != null) {
           if (getCommsInputData().getSubject() != null) {
               subject = getCommsInputData().getSubject();
           }
       }

       return subject;
   }

   
   
   protected RegistryService getRegistryService() throws RuleException {
       try {
           return (RegistryService)this.getComponent(this.getRegistryServiceName());
       }
       catch( ServiceException serviceEx ) {
           throw new RuleException("Error getting RegistryService", serviceEx);
       }
   }

   public boolean isMessageFromVOA() {
       //if GUI flag is set, or
       //sometimes the sendingFacility is not set from UI
       //NOTE: this assumes messages will ALWAYS set and pass the sending facility
       if (this.isUpdateFromGUI() || 
               getSendingFacility() == null)
           return false;
       
       Validate.notNull(getSendingFacility().getCode(), "sendingFacility station number cannot be null");

      return VAFacility.CODE_MHV.getCode().equals(getSendingFacility().getCode());     
   }
       
   
   /**
    * If the sending facility is not VOA, HEC or VBA, then we consider it
    * from Vista
    *  
    * @return
    */
   public boolean isMessageFromVista() {

       //if GUI flag is set, or
       //sometimes the sendingFacility is not set from UI
       //NOTE: this assumes messages will ALWAYS set and pass the sending facility
       if (this.isUpdateFromGUI() || 
               getSendingFacility() == null)
           return false;

       VAFacility facility = getSendingFacility();

       Validate.notNull(facility.getCode(), "sendingFacility station number cannot be null");
       
        return (!VAFacility.CODE_MHV.getCode().equals(facility.getCode()) &&
                !VAFacility.CODE_HEC.getCode().equals(facility.getCode()) &&
                //CCR9565 added one entry to make sure we are including all the non-vista sources
                !VAFacility.CODE_HEC_INCORRECT.getCode().equals(facility.getCode()) &&               
                !VAFacility.CODE_MVR.getCode().equals(facility.getCode()));                       
  }

   // CCR 10311 and CCR 10023 usage
   public boolean isCleanup() {
       return ( (BaseData)this.getRuleDataAware() ).isCleanup();       
   }

    public PersonHelperService getHelperService() {
        return this.helperService;
    }

    public void setHelperService(PersonHelperService service) {
        this.helperService = service;
    }

    /**
     * @return Returns the messagingService.
     */
    public MessagingService getMessagingService() {
        return messagingService;
    }

    /**
     * @param messagingService
     *            The messagingService to set.
     */
    public void setMessagingService(MessagingService messagingService) {
        this.messagingService = messagingService;
    }

    public RelaxationPercentageService getRelaxationPercentageService() {
        return relaxationPercentageService;
    }

    public void setRelaxationPercentageService(
            RelaxationPercentageService relaxationPercentageService) {
        this.relaxationPercentageService = relaxationPercentageService;
    }

    /**
     * @return Returns the mergeRuleService.
     */
    public MergeRuleService getMergeRuleService() {
        return mergeRuleService;
    }

    /**
     * @param mergeRuleService
     *           The mergeRuleService to set.
     */
    public void setMergeRuleService(MergeRuleService mergeRuleService) {
        this.mergeRuleService = mergeRuleService;
    }

    /**
     * @return Returns the lookupService.
     */
    public LookupService getLookupService() {
        return lookupService;
    }

    /**
     * @param lookupService
     *           The lookupService to set.
     */
    public void setLookupService(LookupService lookupService) {
        this.lookupService = lookupService;
    }

    /**
     * @return Returns the eligibilityEnrollmentService.
     */
    public String getEligibilityEnrollmentServiceName() {
        return eligibilityEnrollmentServiceName;
    }

    /**
     * @param eligibilityEnrollmentService
     *           The eligibilityEnrollmentService to set.
     */
    public void setEligibilityEnrollmentServiceName(
            String eligibilityEnrollmentServiceName) {
        this.eligibilityEnrollmentServiceName = eligibilityEnrollmentServiceName;
    }

    /**
     * @return Returns the clinicalDeterminationServiceName.
     */
    public String getClinicalDeterminationServiceName() {
        return clinicalDeterminationServiceName;
    }

    /**
     * @param clinicalDeterminationServiceName
     *           The clinicalDeterminationServiceName to set.
     */
    public void setClinicalDeterminationServiceName(
            String clinicalDeterminationServiceName) {
        this.clinicalDeterminationServiceName = clinicalDeterminationServiceName;
    }

    public String getTimestampManagerName() {
        return timestampManagerName;
    }

    public void setTimestampManagerName(String timestampManagerName) {
        this.timestampManagerName = timestampManagerName;
    }

    /**
     * @return Returns the egtServiceName.
     */
    public String getEgtServiceName() {
        return egtServiceName;
    }

    /**
     * @param egtServiceName
     *           The egtServiceName to set.
     */
    public void setEgtServiceName(String egtServiceName) {
        this.egtServiceName = egtServiceName;
    }

    /**
     * @return Returns the financialsServiceName.
     */
    public String getFinancialsServiceName() {
        return financialsServiceName;
    }

    /**
     * @param financialsServiceName
     *           The financialsServiceName to set.
     */
    public void setFinancialsServiceName(String financialsServiceName) {
        this.financialsServiceName = financialsServiceName;
    }

    /**
     * @return Returns the purpleHeartServiceName.
     */
    public String getPurpleHeartServiceName() {
        return purpleHeartServiceName;
    }

    /**
     * @param purpleHeartServiceName
     *           The purpleHeartServiceName to set.
     */
    public void setPurpleHeartServiceName(String purpleHeartServiceName) {
        this.purpleHeartServiceName = purpleHeartServiceName;
    }

    /**
     * @return Returns the scheduledTaskServiceName.
     */
    public String getScheduledTaskServiceName() {
        return ScheduledTaskServiceName;
    }

    /**
     * @param scheduledTaskServiceName
     *           The scheduledTaskServiceName to set.
     */
    public void setScheduledTaskServiceName(String scheduledTaskServiceName) {
        ScheduledTaskServiceName = scheduledTaskServiceName;
    }

    /**
     * @return Returns the commsLogServiceName.
     */
    public String getCommsLogServiceName() {
        return commsLogServiceName;
    }

    /**
     * @param commsLogServiceName The commsLogServiceName to set.
     */
    public void setCommsLogServiceName(String commsLogServiceName) {
        this.commsLogServiceName = commsLogServiceName;
    }

    // 3.6 CCR 10960 
    public String getHandBookServiceName() {
		return handBookServiceName;
	}

    // 3.6 CCR 10960 
	public void setHandBookServiceName(String handBookServiceName) {
		this.handBookServiceName = handBookServiceName;
	}

	/**
     * @return Returns the workflowService.
     */
    public WorkflowService getWorkflowService() {
        return workflowService;
    }

    /**
     * @param workflowService
     *           The workflowService to set.
     */
    public void setWorkflowService(WorkflowService workflowService) {
        this.workflowService = workflowService;
    }

    /**
     * @param esrImplementationDateString
     *           The esrImplementationDateString to set.
     */
    public void setEsrImplementationDateString(
            String esrImplementationDateString) {
        this.esrImplementationDateString = esrImplementationDateString;
    }

    /**
     * @return Returns the systemParameterService.
     */
    public SystemParameterService getSystemParameterService() {
        return systemParameterService;
    }

    /**
     * @param systemParameterService The systemParameterService to set.
     */
    public void setSystemParameterService(
            SystemParameterService systemParameterService) {
        this.systemParameterService = systemParameterService;
    }

    /**
     * @return Returns the esrImplementationDateString.
     */
    protected String getEsrImplementationDateString() {
        return esrImplementationDateString;
    }

    public String getRegistryServiceName() {
        return registryServiceName;
    }

    public void setRegistryServiceName(String registryServiceName) {
        this.registryServiceName = registryServiceName;
    }
    
    public LogTransmissionService getLogMessagingService() {
		return this.logMessagingService;
	}

	public void setLogMessagingService(
			LogTransmissionService logMessagingService) {
		this.logMessagingService = logMessagingService;
	}

	public ApplicationInProcessService getApplicationInProcessService() {
		return applicationInProcessService;
	}

	public void setApplicationInProcessService(
			ApplicationInProcessService applicationInProcessService) {
		this.applicationInProcessService = applicationInProcessService;
	}

	public VOAApplicationService getVoaApplicationService() {
		return voaApplicationService;
	}

	public void setVoaApplicationService(VOAApplicationService voaApplicationService) {
		this.voaApplicationService = voaApplicationService;
	}
	
}