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

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.HealthBenefitPlanService;
import gov.va.med.esr.service.PersonService;
import gov.va.med.fw.batchprocess.DataProcessExecutionContext;
import gov.va.med.fw.batchprocess.DataQueryProcessExecutionContext;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.support.AbstractSpawnedThreadTask;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;

public class HBPRuleDeploymentProcessSpawnedThreadTask extends
		AbstractSpawnedThreadTask {

	private DataQueryProcessExecutionContext context;
	private BigDecimal acquiredData;
	private HealthBenefitPlanService healthBenefitPlanService;
	private PersonService personService;
	
	public DataQueryProcessExecutionContext getContext() {
		return context;
	}
	public void setContext(DataQueryProcessExecutionContext context) {
		this.context = context;
	}

	public BigDecimal getAcquiredData() {
		return acquiredData;
	}
	public void setAcquiredData(BigDecimal acquiredData) {
		this.acquiredData = acquiredData;
	}
	
	public HealthBenefitPlanService getHealthBenefitPlanService() {
		return healthBenefitPlanService;
	}
	
	public void setHealthBenefitPlanService(HealthBenefitPlanService healthBenefitPlanService) {
		this.healthBenefitPlanService = healthBenefitPlanService;
	}

	
	public PersonService getPersonService() {
		return personService;
	}
	public void setPersonService(PersonService personService) {
		this.personService = personService;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see gov.va.med.fw.service.support.SpawnedThreadTask#execute()
	 */
	public void executeTask() throws Throwable {
		if (logger.isDebugEnabled()) {
			logger.debug("HBPRuleDeploymentProcessSpawnedThreadTask started");
		}

		Person person = null;
		
		try {
			PersonEntityKey key = new PersonIdEntityKeyImpl(acquiredData);		
			person = personService.getPerson(key); 

			if (person == null)
				throw new ServiceException("Unable to find Person with personId= "+ acquiredData);			
	
			healthBenefitPlanService.processHealthBenefitProfile(person);
			
			context.getProcessStatistics().incrementNumberOfSuccessfulRecords();
		}
		catch (Exception e) {
			handleFailure(context, acquiredData, e);
		}
		
		HBPRuleDeploymentProcess.adjustTaskCount(context, -1);
		Object threadCreator = getThreadCreator(context);
		synchronized (threadCreator) {
			threadCreator.notifyAll();
		}
		if (logger.isDebugEnabled()) {
			logger.debug("HBPRuleDeploymentProcessSpawnedThreadTask ended, 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(
						HBPRuleDeploymentProcess.CONTEXT_THREAD_CREATOR);
	}
	
	private void handleFailure(DataQueryProcessExecutionContext context,
			Object dataRecord, Exception e) {
		String exceptionText = null;
		if (e == null) {
			exceptionText = "Error: Unable to process HBP Person data: " + dataRecord;
		}
		else {
				exceptionText = "Error: Unable to process HBP Person data: "
						+ dataRecord + " because of exception: " + e;		
		}
		if (logger.isErrorEnabled()) {
			logger.error(exceptionText);
		}
		context.getProcessStatistics().incrementNumberOfErrorRecords();
		context.getExceptionData().add(dataRecord);
		context.getExceptionData().add(exceptionText + "\n\n");
		
        if ( e != null )
        {
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            String trackTrace =  sw.toString();
            context.getExceptionData().add(trackTrace);
        }
	}
	
	
	
}
