/********************************************************************
 * Copyright © 2006 VHA. All rights reserved
 ********************************************************************/

package gov.va.med.esr.common.batchprocess;

import java.math.BigDecimal;
import java.util.List;

import org.apache.commons.lang.Validate;

import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.id.PersonEntityKey;
import gov.va.med.esr.common.model.person.id.PersonIdEntityKeyImpl;
import gov.va.med.esr.common.model.ee.Eligibility;
import gov.va.med.esr.common.model.ee.EnrollmentDetermination;
import gov.va.med.esr.common.model.lookup.EligibilityType;
import gov.va.med.esr.common.model.ee.ServiceConnectionAward;
import gov.va.med.esr.common.rule.service.EventRuleService;
import gov.va.med.esr.service.EligibilityEnrollmentService;
import gov.va.med.esr.service.LookupService;
import gov.va.med.esr.service.PersonService;
import gov.va.med.fw.batchprocess.AbstractDataQueryIncrementalProcess;
import gov.va.med.fw.batchprocess.DataQueryProcessExecutionContext;
import gov.va.med.fw.model.AbstractEntity;
import gov.va.med.fw.service.ServiceException;

/**
 * Generates QRY-Z11 messages to send to VBA for people with a VBA Query Status
 * of VBA Query Initiated or VBA Queried - Pending Response.
 * 
 * Created Aug 18, 2008 2:39:36 PM
 * @author DNS   GALLAS
 */
public class ReprocessNotFixedVBAQueries extends AbstractDataQueryIncrementalProcess {
	
    private PersonService personService;
    private LookupService lookupService;  
    private EligibilityEnrollmentService eligibilityEnrollmentService;
    
    
    protected void processData(DataQueryProcessExecutionContext context, List acquiredData) {
        if(logger.isDebugEnabled())
            logger.debug(/*Generate Query VBA:*/ getProcessName() + ": Query increment result Size="+(acquiredData == null ? 0 : acquiredData.size()));
        
        if (acquiredData == null)
            return;
        
        // Add check for isInterrupted so don't have to wait for entire batch to finish
        for (int i = 0; i < acquiredData.size() && !isInterrupted(context); i++) {
            // Object[] returned from get when scrolling (idempotent is false)
            Object[] row = (Object[]) acquiredData.get(i);
            BigDecimal personId = (BigDecimal) row[0];
            
            PersonEntityKey key = new PersonIdEntityKeyImpl(personId);
            
            if(logger.isDebugEnabled())
                logger.debug("Processing person # " + (i+1) + " with id = " + personId);
            
            try {
               processRecord(key, row);
               context.getProcessStatistics().incrementNumberOfSuccessfulRecords();
            } catch (Exception ex) {
                context.getProcessStatistics().incrementNumberOfErrorRecords();
                String errMsg = "Error while executing " + getProcessName() + " for person "
                                + personId;
                context.getExceptionData().add(errMsg+ " Reason: "+ ex.getMessage());
                if(logger.isWarnEnabled())
                    logger.warn(errMsg + " Reason: ", ex);
            }
            
            // Update statistics more frequently than once per batch (default size 500)
            if(context.getProcessStatistics().isTotalNumberMod(DEFAULT_JOB_RESULT_UPDATE_INTERVAL))
                this.updateJobResult(context);
        }
        
        if(logger.isDebugEnabled()) {
            logger.debug(/*Generate Query VBA:*/ getProcessName() + ": Processing of current batch complete.");
            logger.debug(/*Generate Query VBA1:*/ getProcessName() + ": Successful records count = "+context.getProcessStatistics().getNumberOfSuccessfulRecords());
            logger.debug(/*Generate Query VBA:*/ getProcessName() + ": Failure records count ="+context.getProcessStatistics().getNumberOfErrorRecords());
        }
    }	

    /**
     * Processes data for a particular person
     * @param key
     * @param VPID
     * @throws ServiceException 
     */
    protected void processRecord(PersonEntityKey key, Object[] dataRow) throws Exception 
    {
        String VPID = (String) dataRow[1];

       	// retrieve Person
		Person personClone = (Person) personService.getPerson(key).clone();
		if (personClone == null)
			throw new RuntimeException("Unable to find Person for VPID: "+ VPID);

		// set primary eligibility = "NSC"
		// deleted from revised white paper
		/*
		if (person.getEnrollmentDetermination() == null) {
	            EnrollmentDetermination enrollmentDetermination = new EnrollmentDetermination();
	            person.setEnrollmentDetermination(enrollmentDetermination);
	    }
		Eligibility eligibility = new Eligibility ();
		eligibility.setType(this.getLookupService().getEligibilityTypeByCode(EligibilityType.NSC.getCode()));
		person.getEnrollmentDetermination().setPrimaryEligiblity(eligibility);
		*/
		
		// set service conected percenteage = null
		if (personClone.getServiceConnectionAward() == null) {
	            ServiceConnectionAward serviceConnectionAward = new ServiceConnectionAward();
	            personClone.setServiceConnectionAward(serviceConnectionAward);
	    }
		personClone.getServiceConnectionAward().setServiceConnectedPercentage(null);

		// invoke determine eligibility
		this.getEligibilityEnrollmentService().updateEligibilityData(personClone);
    }

    public PersonService getPersonService() {
		return personService;
	}

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

    /**
     * @param lookupService The lookupService to set.
     */
    public void setLookupService(LookupService lookupService) {
        this.lookupService = lookupService;
    }    
	/**
	 * @param personService
	 *            The personService to set.
	 */
	public void setPersonService(PersonService personService) {
		this.personService = personService;
	}
	
	 /**
     * @return Returns the eligibilityEnrollmentService.
     */
    public EligibilityEnrollmentService getEligibilityEnrollmentService() {
        return eligibilityEnrollmentService;
    }

    /**
     * @param eligibilityEnrollmentService The eligibilityEnrollmentService to set.
     */
    public void setEligibilityEnrollmentService(
            EligibilityEnrollmentService eligibilityEnrollmentService) {
        this.eligibilityEnrollmentService = eligibilityEnrollmentService;
    }
    
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        Validate.notNull(personService);
        Validate.notNull(lookupService);
        Validate.notNull(eligibilityEnrollmentService);
    }
}
