/********************************************************************
 * Copyright © 2004 EDS. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.util;

// Java classes

// Library classes
// EDB classes
//import gov.va.med.esr.common.constants.EEConstants;
import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.ee.EnrollmentDetermination;
import gov.va.med.esr.common.model.ee.VerificationInfo;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.id.PersonIdEntityKeyImpl;
import gov.va.med.esr.common.rule.data.PersonInputData;
import gov.va.med.esr.common.rule.service.AssociationRuleService;
import gov.va.med.esr.common.rule.service.ClinicalDeterminationRuleService;
import gov.va.med.esr.common.rule.service.CommunicationRuleService;
import gov.va.med.esr.common.rule.service.ContactInfoRuleService;
import gov.va.med.esr.common.rule.service.DemographicRuleService;
import gov.va.med.esr.common.rule.service.EGTRuleService;
import gov.va.med.esr.common.rule.service.EligibilityEnrollmentRuleService;
import gov.va.med.esr.common.rule.service.EligibilityFactorRuleService;
import gov.va.med.esr.common.rule.service.EventRuleService;
import gov.va.med.esr.common.rule.service.FinancialInfoRuleService;
import gov.va.med.esr.common.rule.service.InsuranceRuleService;
import gov.va.med.esr.common.rule.service.MatchRuleService;
import gov.va.med.esr.common.rule.service.MergeRuleService;
import gov.va.med.esr.common.rule.service.MilitaryRuleService;
import gov.va.med.esr.common.rule.service.POWRuleService;
import gov.va.med.esr.common.rule.service.ProcessVBARuleService;
import gov.va.med.esr.common.rule.service.PurpleHeartRuleService;
import gov.va.med.esr.common.rule.service.RuleValidationService;
import gov.va.med.esr.service.WorkflowService;
import gov.va.med.fw.cache.TriggerEventCacheManager;
// Framework classes
import gov.va.med.fw.rule.RuleFlow;
import gov.va.med.fw.rule.RuleParameters;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.validation.ValidationMessages;
import gov.va.med.fw.validation.ValidationServiceException;
import gov.va.med.person.idmgmt.VPID;

import java.math.BigDecimal;

import org.apache.commons.lang.Validate;
import org.springframework.beans.factory.InitializingBean;

/**
 * A class for testing rule sets.
 * 
 * @author Carlos Ruiz
 * @version 1.0
 */
public class RuleAbstractTestCase extends AbstractCommonTestCase implements
        InitializingBean {
    private EventRuleService eventRuleService = null;
    
    private RuleFlow ruleFlowService = null;

    private ContactInfoRuleService contactInfoRuleService = null;

    private ClinicalDeterminationRuleService clinicalDeterminationRuleService = null;

    private DemographicRuleService demographicRuleService = null;

    private EGTRuleService egtRuleService = null;

    private EligibilityFactorRuleService eligibilityFactorRuleService = null;

    private FinancialInfoRuleService financialInfoRuleService = null;

    private InsuranceRuleService insuranceRuleService = null;

    private MatchRuleService matchRuleService = null;
    
    private MergeRuleService mergeRuleService = null;

    private MilitaryRuleService militaryRuleService = null;

    private AssociationRuleService associationRuleService = null;

    private EligibilityEnrollmentRuleService enrollmentRuleService = null;

    private POWRuleService powRuleService = null;

    private PurpleHeartRuleService purpleHeartRuleService = null;
    
    private ProcessVBARuleService processVBARuleService = null;

    private RuleValidationService ruleValidationService = null;
    
    private CommunicationRuleService communicationRuleService = null;
    
    private TriggerEventCacheManager triggerEventCacheManager = null;
    
    private WorkflowService workflowService = null;

    protected static final int PRIMARY_RANK = 1;

    protected static final int SECONDARY_RANK = 2;

    protected static final int OTHER_RANK = 3;

    protected static final String AAC_IND_NewRecordPendingSubmissionToAAC = "01";

    protected static final String AAC_IND_AACQueriedPendingReceiptOfData = "02";

    protected static final String AAC_IND_AACQueriedNoDataReceived = "03";

    protected static final String AAC_IND_EligibilityDeathDataReceivedFromAACAutoUpload = "04";

    protected static final String AAC_IND_DataPendingReview = "05";

    protected static final String AAC_IND_AACDataAcceptedAfterReviewManualUpload = "06";

    protected static final String AAC_IND_AACDataRejected = "07";

    public RuleAbstractTestCase() { super(); }
    
    /**
     * @param testName
     */
    public RuleAbstractTestCase(String testName) {
        super(testName);
    }

    protected EnrollmentDetermination executeDetermineEligibilityRuleSet(
            Person incomingPerson, Person resultPerson, Person pristinePerson,
            boolean fromGUI) throws Exception {

        PersonInputData data = new PersonInputData(incomingPerson,
                resultPerson, pristinePerson, fromGUI);

        this.getRuleFlowService().execute(
                getDetermineEligibilityRuleParameters(), data);

        // extract the calculated enrollment
        return this.getPersonHelperService().getEnrollmentDetermination(
                resultPerson);
    }

    protected Person calculate(Person person) throws Exception {
        return this.getEligibilityEnrollmentService().assessEEImpact(person);
    }

    protected Person verifyEligibility(Person person,
            VerificationInfo verificationInfo) throws Exception {
        // FIXME: Need to discuss with Carlos about input parameter
        // return this.getEnrollmentService().verifyEligibility( person,
        // verificationInfo );
        return null;
    }

    protected Person enrollFromSite(Person person) throws Exception {
        // FIXME: Need to discuss with Carlos about input parameter
        // return this.getEnrollmentService().enroll( person,
        // getVaFacility("200") );
        return null;
    }

    protected Person enrollFromHEC(Person person) throws Exception {
        // FIXME: Need to discuss with Carlos about input parameter
        // return this.getEnrollmentService().enroll( person,
        // getVaFacility("742") );
        return null;
    }

    protected Person setupVBADecision8B(Person person) throws Exception {
        this.attachHousebound(person);
        if (person.getServiceConnectionAward() != null) {
            person.setServiceConnectionAward(null);
        }
        return person;
    }

    protected Person setupVBADecision8C(Person person) throws Exception {
        this.attachVaPension(person);
        if (person.getServiceConnectionAward() != null) {
            person.setServiceConnectionAward(null);
        }
        return person;
    }

    protected Person setupVBADecision8A(Person person) throws Exception {
        this.attachAidAndAttendance(person);
        if (person.getServiceConnectionAward() != null) {
            person.setServiceConnectionAward(null);
        }
        return person;
    }

    // Two methods that will return clone for junit testing
    protected Person savePerson(Person person) throws Exception {
        Person p = this.getPersonService().save(person);
        return (Person)p.clone();
    }
    
    protected Person getPerson(String id) throws Exception {
        PersonIdEntityKeyImpl personKey = new PersonIdEntityKeyImpl(new BigDecimal(id));        
        Person updated = this.getPersonService().getPerson(personKey);
        return updated != null ? (Person)updated.clone() : null;        
    }
    
    protected Person getPersonByVPID(String vpid) throws Exception {
		if (vpid == null)
			return null;
		
		String shortVPID = VPID.getShortVPID(vpid);
		return getPersonService().getPerson(CommonEntityKeyFactory.createVPIDEntityKey(shortVPID));		
	}

    /**
     * @return Returns the determineEligibilityRuleParameters.
     */
    public RuleParameters getDetermineEligibilityRuleParameters()
            throws ServiceException {
        return (RuleParameters)applicationContext.getBean("determineEligibilityRuleParameters");
    }

    /**
     * @return Returns the enrollmentRuleService.
     */
    public EligibilityEnrollmentRuleService getEnrollmentRuleService() {
        return enrollmentRuleService;
    }

    /**
     * @param enrollmentRuleService
     *            The enrollmentRuleService to set.
     */
    public void setEnrollmentRuleService(
            EligibilityEnrollmentRuleService enrollmentRuleService) {
        this.enrollmentRuleService = enrollmentRuleService;
    }

    /**
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    public void afterPropertiesSet() throws Exception {
        Validate.notNull(this.enrollmentRuleService,
                "Enrollment rule service must not be null");
        Validate.notNull(this.getEligibilityEnrollmentService(),
                "Enrollment service must not be null");
        Validate.notNull(this.getLookupService(),
                "Lookup service service must not be null");
        Validate.notNull(this.getPersonHelperService(),
                "Person helper service must not be null");
    }

    /**
     * @return Returns the ruleFlowService.
     */
    public RuleFlow getRuleFlowService() {
        return ruleFlowService;
    }

    /**
     * @param ruleFlowService
     *            The ruleFlowService to set.
     */
    public void setRuleFlowService(RuleFlow ruleFlowService) {
        this.ruleFlowService = ruleFlowService;
    }

    /**
     * @return Returns the contactInfoRuleService.
     */
    public ContactInfoRuleService getContactInfoRuleService() {
        return contactInfoRuleService;
    }

    /**
     * @param contactInfoRuleService
     *            The contactInfoRuleService to set.
     */
    public void setContactInfoRuleService(
            ContactInfoRuleService contactInfoRuleService) {
        this.contactInfoRuleService = contactInfoRuleService;
    }

    /**
     * @return Returns the clinicalDeterminationRuleService.
     */
    public ClinicalDeterminationRuleService getClinicalDeterminationRuleService() {
        return clinicalDeterminationRuleService;
    }

    /**
     * @param clinicalDeterminationRuleService
     *            The clinicalDeterminationRuleService to set.
     */
    public void setClinicalDeterminationRuleService(
            ClinicalDeterminationRuleService clinicalDeterminationRuleService) {
        this.clinicalDeterminationRuleService = clinicalDeterminationRuleService;
    }

    /**
     * @return Returns the demographicRuleService.
     */
    public DemographicRuleService getDemographicRuleService() {
        return demographicRuleService;
    }

    /**
     * @param demographicRuleService
     *            The demographicRuleService to set.
     */
    public void setDemographicRuleService(
            DemographicRuleService demographicRuleService) {
        this.demographicRuleService = demographicRuleService;
    }

    /**
     * @return Returns the egtRuleService.
     */
    public EGTRuleService getEgtRuleService() {
        return egtRuleService;
    }

    /**
     * @param egtRuleService
     *            The egtRuleService to set.
     */
    public void setEgtRuleService(EGTRuleService egtRuleService) {
        this.egtRuleService = egtRuleService;
    }

    /**
     * @return Returns the eligibilityFactorRuleService.
     */
    public EligibilityFactorRuleService getEligibilityFactorRuleService() {
        return eligibilityFactorRuleService;
    }

    /**
     * @param eligibilityFactorRuleService
     *            The eligibilityFactorRuleService to set.
     */
    public void setEligibilityFactorRuleService(
            EligibilityFactorRuleService eligibilityFactorRuleService) {
        this.eligibilityFactorRuleService = eligibilityFactorRuleService;
    }

    /**
     * @return Returns the financialInfoRuleService.
     */
    public FinancialInfoRuleService getFinancialInfoRuleService() {
        return financialInfoRuleService;
    }

    /**
     * @param financialInfoRuleService  The financialInfoRuleService to set.
     */
    public void setFinancialInfoRuleService(
            FinancialInfoRuleService financialInfoRuleService) {
        this.financialInfoRuleService = financialInfoRuleService;
    }

    /**
     * @return Returns the insuranceRuleService.
     */
    public InsuranceRuleService getInsuranceRuleService() {
        return insuranceRuleService;
    }

    /**
     * @param insuranceRuleService The insuranceRuleService to set.
     */
    public void setInsuranceRuleService(
            InsuranceRuleService insuranceRuleService) {
        this.insuranceRuleService = insuranceRuleService;
    }

    /**
     * @return Returns the militaryRuleService.
     */
    public MilitaryRuleService getMilitaryRuleService() {
        return militaryRuleService;
    }

    /**
     * @param militaryRuleService The militaryRuleService to set.
     */
    public void setMilitaryRuleService(MilitaryRuleService militaryRuleService) {
        this.militaryRuleService = militaryRuleService;
    }

    /**
     * @return Returns the personRuleService.
     */
    public AssociationRuleService getAssociationRuleService() {
        return associationRuleService;
    }

    /**
     * @param associationRuleService The personRuleService to set.
     */
    public void setAssociationRuleService(
            AssociationRuleService associationRuleService) {
        this.associationRuleService = associationRuleService;
    }

    /**
     * @return Returns the powRuleService.
     */
    public POWRuleService getPowRuleService() {
        return powRuleService;
    }

    /**
     * @param powRuleService The powRuleService to set.
     */
    public void setPowRuleService(POWRuleService powRuleService) {
        this.powRuleService = powRuleService;
    }

    /**
     * @return Returns the ruleValidationService.
     */
    public RuleValidationService getRuleValidationService() {
        return ruleValidationService;
    }

    /**
     * @param ruleValidationService The ruleValidationService to set.
     */
    public void setRuleValidationService(
            RuleValidationService ruleValidationService) {
        this.ruleValidationService = ruleValidationService;
    }

    /**
     * @return Returns the purpleHeartRuleService.
     */
    public PurpleHeartRuleService getPurpleHeartRuleService() {
        return purpleHeartRuleService;
    }

    /**
     * @param purpleHeartRuleService The purpleHeartRuleService to set.
     */
    public void setPurpleHeartRuleService(
            PurpleHeartRuleService purpleHeartRuleService) {
        this.purpleHeartRuleService = purpleHeartRuleService;
    }

    /**
     * @return Returns the matchRuleService.
     */
    public MatchRuleService getMatchRuleService() {
        return matchRuleService;
    }

    /**
     * @param matchRuleService The matchRuleService to set.
     */
    public void setMatchRuleService(MatchRuleService matchRuleService) {
        this.matchRuleService = matchRuleService;
    }

    /**
     * @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 processVBARuleService.
	 */
	public ProcessVBARuleService getProcessVBARuleService() {
		return processVBARuleService;
	}

	/**
	 * @param processVBARuleService The processVBARuleService to set.
	 */
	public void setProcessVBARuleService(ProcessVBARuleService processVBARuleService) {
		this.processVBARuleService = processVBARuleService;
	}

    /**
     * @return Returns the eventRuleService.
     */
    public EventRuleService getEventRuleService() {
        return eventRuleService;
    }

    /**
     * @param eventRuleService The eventRuleService to set.
     */
    public void setEventRuleService(EventRuleService eventRuleService) {
        this.eventRuleService = eventRuleService;
    }

    /**
     * @return Returns the communicationRuleService.
     */
    public CommunicationRuleService getCommunicationRuleService() {
        return communicationRuleService;
    }

    /**
     * @param communicationRuleService The communicationRuleService to set.
     */
    public void setCommunicationRuleService(
            CommunicationRuleService communicationRuleService) {
        this.communicationRuleService = communicationRuleService;
    }

    /**
     * @return Returns the triggerEventCacheManager.
     */
    public TriggerEventCacheManager getTriggerEventCacheManager() {
        return triggerEventCacheManager;
    }

    /**
     * @param triggerEventCacheManager The triggerEventCacheManager to set.
     */
    public void setTriggerEventCacheManager(
    		TriggerEventCacheManager triggerEventCacheManager) {
        this.triggerEventCacheManager = triggerEventCacheManager;
    }
    
    /**
     * @return Returns the workflowService.
     */
    public WorkflowService getWorkflowService() {
		return workflowService;
	}

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

	protected void fail(String message, Exception e) {
        StringBuffer msg = new StringBuffer();
        msg.append(message);
        if (e instanceof ValidationServiceException) {
            ValidationMessages veMsgs = ((ValidationServiceException)e).getValidationMessages();
            if (veMsgs != null) {
                msg.append(" Validation Messages: ");
                msg.append(veMsgs.getAllMessageText());
                msg.append(" ");
            }
        }
        super.fail(msg.toString(), e);
    }
}