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

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

import gov.va.med.esr.common.model.person.id.PersonIdEntityKeyImpl;
import gov.va.med.esr.common.persistent.financials.RelaxationPercentageDAO;
import gov.va.med.esr.service.EligibilityEnrollmentService;
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.persistent.QueryInfo;

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

import org.apache.commons.lang.Validate;

/**
 * Batch Process to reevaluate veterans based on a changed relaxation
 * percentage.
 * 
 * @author DNS   barryc
 */
public class RelaxationPercentageRetroactiveProcess extends
		AbstractDataQueryIncrementalProcess {

	// -------------------------------------------------------- Fields

	private EligibilityEnrollmentService eligibilityEnrollmentService;
	private RelaxationPercentageDAO relaxationPercentageDAO;

	// -------------------------------------------------------- Business Methods

	/**
	 * @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.isInfoEnabled())
			logger.info("RelaxationPercentageRetroactiveProcess batch process: processing "
					+ (acquiredData == null ? 0 : acquiredData.size())
					+ " rows from source query");

		if (acquiredData == null)
			return;

		ProcessStatistics stats = context.getProcessStatistics();

		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];

			if (logger.isDebugEnabled())
				logger.error("Processing person ID  " + personId);

			try {
				/*
				 * recalculate EE rules for patient to see if they qualify after
				 * change in Relaxation Percentage value
				 */
				eligibilityEnrollmentService.processCalculateEEForCleanup(
						new PersonIdEntityKeyImpl(personId), true, true);
				stats.incrementNumberOfSuccessfulRecords();
			} catch (Exception e) {
				if (logger.isErrorEnabled())
					logger.error(
							"Error during RelaxationPercentageRetroactiveProcess for person ID "
									+ personId, e);
				stats.incrementNumberOfErrorRecords();
			}

			if (stats.isTotalNumberMod(DEFAULT_JOB_RESULT_UPDATE_INTERVAL))
				updateJobResult(context);
		}

		if (logger.isDebugEnabled()) {
			logger.debug("RelaxationPercentageRetroactiveProcess: Processing of current batch complete.");
			logger.debug("RelaxationPercentageRetroactiveProcess: Successful records count = "
					+ stats.getNumberOfSuccessfulRecords());
			logger.debug("RelaxationPercentageRetroactiveProcess: Failure records count ="
					+ stats.getNumberOfErrorRecords());
		}
	}

	protected List doAcquireData(DataQueryProcessExecutionContext context)
			throws Exception {
		QueryInfo query = context.getCurrentDataQuery().getQuery();
		query.setFetchSize(getFetchSize());

		String executionArgument = (String)context.getExecutionArguments();
		if (executionArgument == null )

			throw new Exception(
					"Required execution argument \"incomeYear\" was not set."
							+ " Value should be a single four-digit Integer representing"
							+ " the income year for which we are retroactively processing people.");

		Integer incomeYear = new Integer(executionArgument);
		
		query.setParamNames(new String[] {"incomeYear"});
		query.setParamValues(new Object[] {incomeYear});
		getDao().scroll(this, query, context);
		return null;
	}

	public void afterPropertiesSet() {
		super.afterPropertiesSet();
		Validate.notNull(eligibilityEnrollmentService);
		Validate.notNull(relaxationPercentageDAO);
	}

	// -------------------------------------------------------- Accessor Methods

	public void setEligibilityEnrollmentService(
			EligibilityEnrollmentService eligibilityEnrollmentService) {
		this.eligibilityEnrollmentService = eligibilityEnrollmentService;
	}

	public void setRelaxationPercentageDAO(
			RelaxationPercentageDAO relaxationPercentageDAO) {
		this.relaxationPercentageDAO = relaxationPercentageDAO;
	}

}
