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

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

import gov.va.med.esr.common.model.lookup.ComLetterTemplateType;
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.service.CommsLetterRequestService;
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.batchprocess.ProcessStatistics;
import gov.va.med.fw.rule.RuleException;
import gov.va.med.esr.service.LookupService;
import gov.va.med.esr.service.PersonHelperService;
import gov.va.med.esr.service.PersonService;
import gov.va.med.esr.service.trigger.LetterTrigger;
import gov.va.med.esr.service.trigger.LetterTriggerEvent;
import gov.va.med.esr.service.trigger.LetterTriggerIdentity;
import gov.va.med.fw.service.ServiceException;

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

import org.apache.commons.lang.Validate;

/**
 * Initial Batch Process for triggering 640K Letter for Catastrophic Disabled Recipients.
 * 
 * @author DNS   CHANA
 */
public class Initial640KLetterBatch extends AbstractDataQueryIncrementalProcess {

    private PersonService personService;
    private LookupService lookupService;  
    private CommsLetterRequestService letterRequestService = null;
	private ComLetterTemplateType formNumber = null;

     
	/**
	 * @see gov.va.med.fw.batchprocess.AbstractDataProcess#processData(gov.va.med.fw.batchprocess.DataProcessExecutionContext,
	 *      java.util.List)
	 */
	protected void processData(DataQueryProcessExecutionContext context, List acquiredData) {
		if(logger.isDebugEnabled())
			logger.debug("Initial 640K Letter batch process: Query increment result Size="+(acquiredData == null ? 0 : acquiredData.size()));
		
		if (acquiredData == null)
			return;

        // TODO it should be FORM_NUMBER_640K
        try{
        	this.formNumber = getComLetterTemplateType(ComLetterTemplateType.FORM_NUMBER_640K.getName());
        } catch (RuleException ex){
        	return;
        }
        if ( this.formNumber==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(getProcessName() + ": Processing of current batch complete.");
            logger.debug(getProcessName() + ": Successful records count = "+context.getProcessStatistics().getNumberOfSuccessfulRecords());
            logger.debug(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];
		Person person = personService.getPerson(key);

		if (person == null)
			throw new RuntimeException("Unable to find Person for VPID: "+ VPID);

		

		letterRequestService.requestAacLetter(person, new LetterTriggerIdentity(this.formNumber, LetterTrigger.CategoryType.VETERAN_LETTER), null, LetterTriggerEvent.MANUAL_MAIL, null);	
    }
	
    
    private ComLetterTemplateType getComLetterTemplateType(String type) throws RuleException {
    	if (type != null) 
    	{
    		try {
    			return this.getLookupService().getComLetterTemplateTypeByCode(type);
    		} catch (ServiceException e) {
    			throw new RuleException( "Failed to get com letter template type", e);
    		}
    	}
    	return null;
    }
    /* letterRequestService
     * 
     */
    public CommsLetterRequestService getLetterRequestService() {
		return letterRequestService;
	}
    
	public void setLetterRequestService(CommsLetterRequestService letterRequestService) {
		this.letterRequestService = letterRequestService;
	}

    /**
	 * @param personService
	 *            The personService to set.
	 */
	public void setPersonService(PersonService personService) {
		this.personService = personService;
	}
	
    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;
    }    	
	
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        Validate.notNull(personService);
        Validate.notNull(lookupService);
        Validate.notNull(letterRequestService);   
    }
}
