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

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

import java.util.List;

import org.apache.commons.lang.Validate;

import gov.va.med.fw.batchprocess.DataFileProcessExecutionContext;
import gov.va.med.fw.batchprocess.DataProcessExecutionContext;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.support.AbstractSpawnedThreadTask;
import gov.va.med.fw.util.builder.Builder;
import gov.va.med.fw.util.builder.BuilderException;

import gov.va.med.esr.common.batchprocess.datasync.HECLegacyDataSynchronizationConsumerProcess;
import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.comms.HandBookBatchRequest;
import gov.va.med.esr.common.model.ee.PrisonerOfWar;
import gov.va.med.esr.common.model.ee.PurpleHeart;
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.registry.Registry;
import gov.va.med.esr.common.model.registry.RegistryTrait;
import gov.va.med.esr.service.HandBookService;
import gov.va.med.esr.service.PersonService;
import gov.va.med.esr.service.RegistrySearchCriteria;
import gov.va.med.esr.service.RegistrySearchResultBean;
import gov.va.med.esr.service.RegistryService;

/**
 * Prototype Spring bean for concurrent processing of file data.
 * 
 * Created May 3, 2006 5:31:00 PM
 * 
 * @author DNS   BOHMEG
 */
public class HandBookBatchRequestConsumerSpawnedThreadTask extends
		AbstractSpawnedThreadTask {
	private DataFileProcessExecutionContext context;

	private List acquiredData;

	
	private HandBookService handBookService;

	
	public HandBookService getHandBookService() {
		return handBookService;
	}

	public void setHandBookService(HandBookService handBookService) {
		this.handBookService = handBookService;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see gov.va.med.fw.service.support.SpawnedThreadTask#execute()
	 */
	public void executeTask() throws Throwable {
		if (logger.isDebugEnabled()) {
			logger.debug("HECLegacyDataSynchronizationConsumerSpawnedThreadTask started");
		}
		// ordering implied here for the first element (must be identity
		// information)
		HandBookBatchRequest handBookBatchRequest = (HandBookBatchRequest) acquiredData.get(0);
		try {
			this.handBookService.updateBatchRequestEstCountRecord(handBookBatchRequest);
				
		} catch (Exception e) {
			handleFailure(context, acquiredData, e);
		} finally {
			if (logger.isDebugEnabled()) {
				logger.debug("HECLegacyDataSynchronizationConsumerSpawnedThreadTask ended");
			}
				Object threadCreator = getThreadCreator(context);
			synchronized (threadCreator) {
				threadCreator.notifyAll();
			}
			if (logger.isDebugEnabled()) {
				logger.debug("HECLegacyDataSynchronizationConsumerSpawnedThreadTask notified creator");
			}
			
			/*
			 * force release of context as thay will hold the ThreadPool(->Threads)
			 * this is necessary to GC ThreadPool threads at end
			 */
			context = null;
		}
	}

	private Object getThreadCreator(DataProcessExecutionContext context) {
		return context
				.getContextData()
				.get(
						HECLegacyDataSynchronizationConsumerProcess.CONTEXT_THREAD_CREATOR);
	}

	

	
	private void handleFailure(DataFileProcessExecutionContext context,
			List identityData, Exception e) {

		String exceptionText = null;
		
		if (e == null) {
			exceptionText = "Error: Unable to synchronize data for identity data: " + identityData;
		}
		else {
			if(e instanceof BuilderException) {
				// do this since reflection is being used...
				Throwable cause = e.getCause(); // typically this is a non-helpful reflection exception 
				Throwable causesCause = cause != null ? cause.getCause() : null;
				
				exceptionText = "Error: Unable to synchronize data for identity data: "
						+ identityData;
				if (causesCause != null) {
					exceptionText += " because of BuilderException with cause: " + cause + " and causes cause: " + causesCause;
				}
			}
			else {
				exceptionText = "Error: Unable to synchronize data for identity data: "
						+ identityData + " because of exception: " + e;		
			}
		}
		
		if (logger.isErrorEnabled()) {
			logger.error(exceptionText);
		}
		context.getProcessStatistics().incrementNumberOfErrorRecords();
		context.getExceptionData().add(identityData);
		context.getExceptionData().add(exceptionText + "\n\n");
	}

	/**
	 * @return Returns the acquiredData.
	 */
	public List getAcquiredData() {
		return acquiredData;
	}

	/**
	 * @param acquiredData
	 *            The acquiredData to set.
	 */
	public void setAcquiredData(List acquiredData) {
		this.acquiredData = acquiredData;
	}
 
	/**
	 * @return Returns the context.
	 */
	public DataFileProcessExecutionContext getContext() {
		return context;
	}

	/**
	 * @param context
	 *            The context to set.
	 */
	public void setContext(DataFileProcessExecutionContext context) {
		this.context = context;
	}

	
	
	public void afterPropertiesSet() {
		Validate.notNull(handBookService, "personService can not be null");
		}



}
