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

// Java classes
import java.util.Map;
import java.util.HashMap;

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

// Framework classes
import gov.va.med.fw.rule.RuleParameters;
import gov.va.med.fw.service.ServiceException;

// EDB classes
import gov.va.med.esr.common.model.ee.VerificationInfo;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.rule.service.ProcessVBARuleService;
import gov.va.med.esr.common.rule.data.PersonInputData;
import gov.va.med.esr.common.rule.data.AssociationInputData;
import gov.va.med.esr.common.rule.data.EEInputData;
import gov.va.med.esr.common.rule.data.IneligibilityInputData;

/**
 * Project: Common
 * @author DNS   LEV
 * @version 1.0
 */
public class ProcessVBARuleServiceImpl extends AbstractRuleValidationServiceAwareImpl implements
         ProcessVBARuleService {

   /**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = -4624827103975543507L;

	/**
	 * An instance of processVBARuleParameters
	 */
	private String processVBARuleParameters = null;
	
	/**
	 * An instance of processVBADataRuleParameters
	 */
	private String processVBADataRuleParameters = null;
	
	/**
	 * An instance of personRuleParameterName
	 */
	private String personRuleParameterName = null;
	/**
	 * An instance of communicationsRuleParameterName
	 */
	private String communicationsRuleParameterName = null;
   /**
    * An instance of associationRuleParameterName
    */
   private String associationRuleParameterName = null;
	/**
	 * An instance of demographicRuleParameterName
	 */
	private String demographicRuleParameterName = null;
	/**
	 * An instance of eligibleVerificationRuleParameterName
	 */
	private String eligibleVerificationRuleParameterName = null;
	/**
	 * An instance of enrollmentRuleParameterName
	 */
	private String enrollmentRuleParameterName = null;
	/**
	 * An instance of ineligibleRuleParameterName
	 */
	private String ineligibleRuleParameterName = null;
	/**
	 * An instance of monetaryAwardRuleParameterName
	 */
	private String monetaryAwardRuleParameterName = null;
   
   /**
    * An instance of militaryServiceRuleParameter 
    */
   private String militaryServiceRuleParameter = null;
   
	/**
	 * An instance of serviceConnectionRuleParameterName
	 */
	private String serviceConnectionRuleParameterName = null;
	/**
	 * An instance of facilityRuleParameterName
	 */
	private String facilityRuleParameterName = null;
	/**
	 * An instance of workloadRuleParameterName
	 */
	private String workloadRuleParameterName = null;
	/**
    * A default constructor
    */
   public ProcessVBARuleServiceImpl() {
      super();
   }

   /**
    * @see gov.va.med.esr.common.rule.service.impl.AbstractRuleValidationServiceAwareImpl#afterPropertiesSet()
    */
   public void afterPropertiesSet() throws Exception {
      super.afterPropertiesSet();
      Validate.notNull( this.processVBARuleParameters, "processVBARuleParameters property is required");
   }

   /**
    * Returns an instance of militaryServiceRuleParameter
    * @return String militaryServiceRuleParameter.
    */
   public String getMilitaryServiceRuleParameter() {
      return militaryServiceRuleParameter;
   }

   /**
    * Sets the militaryServiceRuleParameter of type String
    * @param militaryServiceRuleParameter The militaryServiceRuleParameter to set.
    */
   public void setMilitaryServiceRuleParameter(String militaryServiceRuleParameter) {
      this.militaryServiceRuleParameter = militaryServiceRuleParameter;
   }

   /**
    * @see gov.va.med.esr.common.rule.service.ProcessVBARuleService#verifyEligibility(gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.model.ee.VerificationInfo)
    */
   public Person verifyEligibility( Person incoming, Person updated, VerificationInfo info ) throws ServiceException {

   	Validate.notNull( updated, "A person being updated must not be NULL" );
   	Validate.notNull( incoming, "An incoming person must not be NULL" );
   	Validate.notNull( info, "A verification information must not be NULL" );
   	
   	// Get a pristine person 
   	Person pristine = this.getPristinePerson( updated );
   	
		// Initialize rule parameters with rule data
   	RuleParameters parameters = this.getRuleParameters( getProcessVBARuleParameters() );
   	
   	// Invoke a rule flow with parameters populated with BOM objects
   	this.invokeRuleFlow( parameters, 
                           this.initializeVBARuleParameters( incoming, updated, pristine, info ) );
   	
   	return updated;
   }

   /**
    * @see gov.va.med.esr.common.rule.service.ProcessVBARuleService#processVBAData(gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.model.ee.VerificationInfo)
    */
   public Person processVBAData( Person incoming, VAFacility sendingFacility, Person updated, VerificationInfo info ) throws ServiceException {

   	Validate.notNull( updated, "A person being updated must not be NULL" );
   	Validate.notNull( incoming, "An incoming person must not be NULL" );
   	
   	// Get a pristine person 
   	Person pristine = this.getPristinePerson( updated );
   	
		// Initialize rule parameters with rule data
   	RuleParameters parameters = this.getRuleParameters( getProcessVBADataRuleParameters() );
   	
   	// Invoke a rule flow with parameters populated with BOM objects
   	this.invokeRuleFlow( parameters, 
                           this.initializeVBADataParameters( incoming, sendingFacility, updated, pristine, info ) );
   	
   	return updated;
   }
   
	/**
	 * @return Returns the processVBADataRuleParameters.
	 */
	public String getProcessVBADataRuleParameters() {
		return processVBADataRuleParameters;
	}

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

	/**
	 * @return Returns the processVBARuleParameters.
	 */
	public String getProcessVBARuleParameters() {
		return processVBARuleParameters;
	}

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

	/**
	 * @return Returns the communicationsRuleParameterName.
	 */
	public String getCommunicationsRuleParameterName() {
		return communicationsRuleParameterName;
	}

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

	/**
	 * @return Returns the demographicRuleParameterName.
	 */
	public String getDemographicRuleParameterName() {
		return demographicRuleParameterName;
	}

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

	/**
	 * @return Returns the eligibleVerificationRuleParameterName.
	 */
	public String getEligibleVerificationRuleParameterName() {
		return eligibleVerificationRuleParameterName;
	}

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

	/**
	 * @return Returns the enrollmentRuleParameterName.
	 */
	public String getEnrollmentRuleParameterName() {
		return enrollmentRuleParameterName;
	}

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

	/**
	 * @return Returns the ineligibleRuleParameterName.
	 */
	public String getIneligibleRuleParameterName() {
		return ineligibleRuleParameterName;
	}

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

	/**
	 * @return Returns the monetaryAwardRuleParameterName.
	 */
	public String getMonetaryAwardRuleParameterName() {
		return monetaryAwardRuleParameterName;
	}

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

	/**
	 * @return Returns the personRuleParameterName.
	 */
	public String getPersonRuleParameterName() {
		return personRuleParameterName;
	}

	/**
	 * @param personRuleParameterName The personRuleParameterName to set.
	 */
	public void setPersonRuleParameterName(String personRuleParameterName) {
		this.personRuleParameterName = personRuleParameterName;
	}
	/**
	 * @return Returns the serviceConnectionRuleParameterName.
	 */
	public String getServiceConnectionRuleParameterName() {
		return serviceConnectionRuleParameterName;
	}
	/**
	 * @param serviceConnectionRuleParameterName The serviceConnectionRuleParameterName to set.
	 */
	public void setServiceConnectionRuleParameterName(
			String serviceConnectionRuleParameterName) {
		this.serviceConnectionRuleParameterName = serviceConnectionRuleParameterName;
	}
	/**
	 * @return Returns the facilityRuleParameterName.
	 */
	public String getFacilityRuleParameterName() {
		return facilityRuleParameterName;
	}

	/**
	 * @param facilityRuleParameterName The facilityRuleParameterName to set.
	 */
	public void setFacilityRuleParameterName(String facilityRuleParameterName) {
		this.facilityRuleParameterName = facilityRuleParameterName;
	}
	/**
	 * @return Returns the workloadRuleParameterName.
	 */
	public String getWorkloadRuleParameterName() {
		return workloadRuleParameterName;
	}

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

   /**
    * Returns an instance of associationRuleParameterName
    * @return String associationRuleParameterName.
    */
   public String getAssociationRuleParameterName() {
      return associationRuleParameterName;
   }

   /**
    * Sets the associationRuleParameterName of type String
    * @param associationRuleParameterName The associationRuleParameterName to set.
    */
   public void setAssociationRuleParameterName(String associationRuleParameterName) {
      this.associationRuleParameterName = associationRuleParameterName;
   }
	/** Initializes a map containing rule data for each rule parameter
	 * @param incoming
	 * @param onFile
	 * @param pristine
	 * @param info
	 * @return
	 */
	private Map initializeVBARuleParameters( Person incoming, 
                                            Person onFile, 
                                            Person pristine, 
                                            VerificationInfo info ) 
		throws ServiceException {

		// Initialize rule parameters with rule data
		Map data = new HashMap();
   	
      // Initialize rule data for an association rule parameter
      AssociationInputData associationData = new AssociationInputData( incoming, onFile, pristine );
      data.put( this.getAssociationRuleParameterName(), associationData );
      
      // Initialize rule data for a communications rule parameter
      PersonInputData ruleData = new PersonInputData( incoming, onFile, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
      data.put( this.getCommunicationsRuleParameterName(), ruleData );
      
		// Initialize rule data for a demographic rule parameter
		ruleData = new PersonInputData( incoming, onFile, pristine, info );
		ruleData.setPersonService( this.getPersonService() );
		data.put( this.getDemographicRuleParameterName(), ruleData );
		
		// Initialize rule data for an eligibility rule parameter
		ruleData = new EEInputData( incoming, onFile, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
		data.put( this.getEligibleVerificationRuleParameterName(), ruleData );

		// Initialize rule data for an enrollment rule parameter
		ruleData = new EEInputData( incoming, onFile, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
		data.put( this.getEnrollmentRuleParameterName(), ruleData );
		
		// Initialize rule data for an ineligible rule parameter
		ruleData = new IneligibilityInputData( incoming, onFile, pristine, false, info );
      ruleData.setPersonService( this.getPersonService() );
   	data.put( this.getIneligibleRuleParameterName(), ruleData );
   	
      // Initialize rule data for a military rule parameter
      ruleData = new PersonInputData( incoming, onFile, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
      data.put( this.getMilitaryServiceRuleParameter(), ruleData );
      
		// Initialize rule data for a monetary rule parameter
		ruleData = new PersonInputData( incoming, onFile, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
   	data.put( this.getMonetaryAwardRuleParameterName(), ruleData );
   	
      // Initialize rule data for a person rule parameter
      ruleData = new PersonInputData( incoming, onFile, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
      data.put( this.getPersonRuleParameterName(), ruleData );
      
		// Initialize rule data for a service connection rule parameter
		ruleData = new PersonInputData( incoming, onFile, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
   	data.put( this.getServiceConnectionRuleParameterName(), ruleData );
   	
		// Initialize rule data for a workload rule parameter
		ruleData = new PersonInputData( incoming, onFile, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
   	data.put( this.getWorkloadRuleParameterName(), ruleData );
   	
		return data;
	}
	
	/** Initializes a map containing rule data for each rule parameter
	 * @param incoming
	 * @param onFile
	 * @param pristine
	 * @return
	 */
	private Map initializeVBADataParameters( Person incoming, 
											 VAFacility sendingFacility, //added for isMessageFromVOA to work correctly
                                             Person updated, 
                                             Person pristine,
                                             VerificationInfo info ) { 

		// Initialize rule parameters with rule data
		Map data = new HashMap();

		// Initialize rule data for a communications rule parameter
		PersonInputData ruleData = new PersonInputData(incoming, updated, pristine,
		         sendingFacility, info);
      ruleData.setPersonService( this.getPersonService() );
		data.put( this.getCommunicationsRuleParameterName(), ruleData );

		// Initialize rule data for an eligibility rule parameter
      ruleData = new EEInputData( incoming, updated, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
		data.put( this.getEligibleVerificationRuleParameterName(), ruleData );
		
		// Initialize rule data for an enrollment rule parameter
      ruleData = new EEInputData( incoming, updated, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
		data.put( this.getEnrollmentRuleParameterName(), ruleData );
		
      // Initialize rule data for a facility rule parameter
      ruleData = new PersonInputData( incoming, updated, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
      data.put( this.getFacilityRuleParameterName(), ruleData );
      
      // Initialize rule data for an ineligible rule parameter
      ruleData = new IneligibilityInputData( incoming, updated, pristine, false, info );
      ruleData.setPersonService( this.getPersonService() );
      data.put( this.getIneligibleRuleParameterName(), ruleData );
      
		// Initialize rule data for a monetary rule parameter
		ruleData = new PersonInputData( incoming, updated, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
   	data.put( this.getMonetaryAwardRuleParameterName(), ruleData );
   	
      // Initialize rule data for a military service rule parameter
      ruleData = new PersonInputData( incoming, updated, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
      data.put( this.getMilitaryServiceRuleParameter(), ruleData );
      
		// Initialize rule data for a person rule parameter
      ruleData = new PersonInputData( incoming, updated, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
		data.put( this.getPersonRuleParameterName(), ruleData );
		
		// Initialize rule data for a service connection rule parameter
      ruleData = new PersonInputData( incoming, updated, pristine, info );
      ruleData.setPersonService( this.getPersonService() );
   	data.put( this.getServiceConnectionRuleParameterName(), ruleData );
   	
		return data;
	}
}