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

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.ee.CancelDecline;
import gov.va.med.esr.common.model.lookup.CancelDeclineReason;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.id.PersonIdEntityKey;
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.AbstractDataFileIncrementalProcess;
import gov.va.med.fw.batchprocess.DataFileProcessExecutionContext;
import gov.va.med.fw.batchprocess.FailedRecordWriterProcessCompletedHandler;
import gov.va.med.fw.service.ServiceException;

/**
 * CCR13649
 * Sets records to status Cancel/Decline with reason: Other and remarks: Abandoned Application
 * that are identified for cleanup
 * Input file is list of veteran person_id, vpid, and cancel decline date identified by HEC
 *
 * Created Feb 17, 2015
 * @author DNS   faulkj
 */
public class AbandonedApplicationCleanupProcess extends
	AbstractDataFileIncrementalProcess {

	private EligibilityEnrollmentService eligibilityEnrollmentService = null;
	private PersonService personService = null;
	private LookupService lookupService = null;


	@Override
	public void processDataRecords(DataFileProcessExecutionContext context, List acquiredData) {

		for ( int i=0; acquiredData != null && i< acquiredData.size(); i++)
        {
			AbandonedAppData dataRecord = (AbandonedAppData) acquiredData.get(i);

			PersonIdEntityKey personKey = null;
    		String vpid_value = null;
    		SimpleDateFormat input = new SimpleDateFormat("yyyyMMdd");
        	Date effectiveDate = null;

        	try {

        		//get elements from input data record
        		personKey = CommonEntityKeyFactory.createPersonIdEntityKey(dataRecord.getPersonId());
        		vpid_value = dataRecord.getVpid();
	        	effectiveDate = input.parse(dataRecord.getDate());

	        	Person incoming = this.getPersonService().getPerson(personKey);
	        	if (incoming == null) {
	        		throw new ServiceException("Person Not Found: " + vpid_value);
	        	}

	        	if (logger.isDebugEnabled())
                       logger.debug("Abandoned Application Cleanup Process - Processing person " + incoming.toString());

	        	//default cancelDecline record for every person identified
	        	//indicator=true, reason=other, remarks=abandoned application, date=input effective date
	        	CancelDecline cancelDecline = new CancelDecline();
	        	cancelDecline.setCancelDeclineIndicator(Boolean.TRUE);
	        	cancelDecline.setReason(lookupService.getCancelDeclineReasonByCode(
	        			CancelDeclineReason.CODE_OTHER.getName()));
	        	cancelDecline.setEffectiveDate(effectiveDate);
	        	cancelDecline.setRemarks("Abandoned Application");

	        	incoming.setCancelDecline(cancelDecline);

	        	//kick off enrollment rule flows and trigger events for updated person
	        	this.getEligibilityEnrollmentService().updateEnrollmentData(incoming);

	        	if (logger.isDebugEnabled())
                    logger.debug("Abandoned Application Cleanup Process - Completed Processing person " + incoming.toString());

                context.getProcessStatistics().incrementNumberOfSuccessfulRecords();

            } catch (Exception e) {
                if (logger.isErrorEnabled())
                	logger.error("Error during Abandoned Application Cleanup Process for person ID " + dataRecord.getPersonId(), e);

                context.getProcessStatistics().incrementNumberOfErrorRecords();

                //put first 1500 chars of stack trace element into exception file
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                String trace = sw.toString();
                int len = 1500;
                if (trace.length() < 1500) len = trace.length();

                context.getExceptionData().add(personKey.getKeyValueAsString() + "^" + vpid_value + "^" + e.getMessage() + "^" + trace.substring(0, len-1));
            }
            finally
            {
                // Check if we need to update the job result
                if(shouldUpdateJobResult(context))
                        updateJobResult(context);

                if ( isInterrupted(context))
                {
                    break;
                }
            }

        }
		//write to the exception and failed file data at the end of the job.
		FailedRecordWriterProcessCompletedHandler dataFileCompletedHandler  = (FailedRecordWriterProcessCompletedHandler)getDataProcessCompletedHandler();
		dataFileCompletedHandler.writeExceptionData(context);
		dataFileCompletedHandler.writeFailedData(context);

	}

	public EligibilityEnrollmentService getEligibilityEnrollmentService() {
		return eligibilityEnrollmentService;
	}

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

	public PersonService getPersonService() {
		return personService;
	}

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

	public LookupService getLookupService() {
		return lookupService;
	}

	public void setLookupService(LookupService lookupService) {
		this.lookupService = lookupService;
	}
}
