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

import gov.va.med.esr.common.model.cases.Status;
import gov.va.med.esr.common.model.cases.WorkflowCase;
import gov.va.med.esr.common.model.lookup.WkfCaseStatusType;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.service.LookupService;
import gov.va.med.fw.persistent.hibernate.AbstractDAOAction;
import gov.va.med.fw.batchprocess.AbstractDataQueryIncrementalProcess;
import gov.va.med.fw.batchprocess.DataQueryProcessExecutionContext;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.transaction.TransactionTimestampManager;

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

import org.hibernate.Query;
import org.hibernate.Session;

/**
 * The batch process to update the country code of a person permanent address
 * if it's null. This process will start only one time when the server starts,
 * but can be invoked manually later.
 * Created Oct 05, 2008 09:10:46 AM
 * @author DNS   DOANK
 */
public class UpdateEmptyCountryCodeProcess extends
		AbstractDataQueryIncrementalProcess {
	private static final String UPDATE_COUNTRY_CODE = "updateEmptyCountryCode_updateCountry";
    private static final String PARAM_COUNTRY_CODE = "addressId";
    private static final String PARAM_CASEID = "caseId";
    private static final String CLOSE_WORKCASE = "updateEmptyCountryCodeProcess.closeWorkcase"; 
    
	LookupService lookupService;
	TransactionTimestampManager timestampManager;
	
	protected void processData(DataQueryProcessExecutionContext context,
			List acquiredData) {
		if(logger.isDebugEnabled())
            logger.debug("Update Empty Country Code batch process: Query increment result Size="+(acquiredData == null ? 0 : acquiredData.size()));
        
        if (acquiredData == null)
            return;
        WkfCaseStatusType closedStatusType = null;
        try
        {
        	closedStatusType = (WkfCaseStatusType)getLookupService().getWkfCaseStatusTypeByCode(WkfCaseStatusType.CLOSED.getName());
        }
        catch (ServiceException ex)
        {
        	String errMsg = "Error while executing Update Empty Country Code batch process";
        	context.getExceptionData().add(errMsg+ " Reason: "+ ex.getMessage());
        	if(logger.isWarnEnabled())
        		logger.warn(errMsg + " Reason: ", ex);
        	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 wkfCaseId = (BigDecimal) row[0];
            BigDecimal wkfStatusId = (BigDecimal)row[1];
            String errorText = (String)row[2];
            BigDecimal addressId = (BigDecimal) row[3];
            String country_code = (String) row[4];
            
            if(logger.isDebugEnabled())
                logger.debug("Processing Workflow Case # " + (i+1) + " with id = " + wkfCaseId);
            
            try {
            	 
                // CCR#9891 1.  For every workload case containing "Country Required", if the permanent address has country = Null and a Zip code that is associated with a US state, populate the country with USA and close the workload.  (This is the way the current batch process works.)
                // Not closing the workflow Case.
            	if(country_code  == null) //When country has not been updated previously
            	{
                    
                    Map contextData = new HashMap();
                    contextData.put("addressId", addressId);      
                    AbstractDAOAction callback = new AbstractDAOAction(contextData) { 
                        public Object execute(Session session) {
                        Query query = session.getNamedQuery(UPDATE_COUNTRY_CODE);
                        query.setParameter(PARAM_COUNTRY_CODE, (BigDecimal)getContextData().get("addressId"));
                        return new Integer(query.executeUpdate());  
                         }
                    };
            		//DNS   doank CCR8648: Now there's a requirement to not trigger an outgoing z05 message
            		//address.setChangeDate(getTimestampManager().getTransactionTimestamp());
                    Integer updateCount = (Integer) getDao().execute(callback);
                    if (updateCount.intValue() < 1) {
                        if(logger.isWarnEnabled())
                        logger.warn(getProcessName() + ": Country code cannot be updated for " + addressId);
                    }
                    
            	}
            	
            	
            	//if COUNTRY_REQUIRED is the only error and the work item is not closed
                // 2.  For every workload case containing "Country Required", if the permanent address has country NOT = Null, then close the workload item.
            	//                finally, close the workflow case
                    Map contextData = new HashMap();
                    contextData.put("caseId", wkfCaseId);      
                    AbstractDAOAction callback = new AbstractDAOAction(contextData) { 
                        public Object execute(Session session) {
                            Query query = session.getNamedQuery(CLOSE_WORKCASE);
                            query.setParameter(PARAM_CASEID, (BigDecimal)getContextData().get("caseId"));
                            return new Integer(query.executeUpdate());  
                         }
                    };
                 
                    Integer updateCount = (Integer) getDao().execute(callback);
                    if (updateCount.intValue() < 1) {
                        if(logger.isWarnEnabled())
                            logger.warn(getProcessName() + ": Workflow case status not updated to Closed for caseId=" + wkfCaseId);
                    }
            		
                context.getProcessStatistics().incrementNumberOfSuccessfulRecords();
            } catch (Exception ex) {
                context.getProcessStatistics().incrementNumberOfErrorRecords();
                String errMsg = "Error while executing Update Empty Country Code batch process for Workflow Case "
                                + wkfCaseId;
                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 5)
            if(context.getProcessStatistics().isTotalNumberMod(DEFAULT_JOB_RESULT_UPDATE_INTERVAL))
                this.updateJobResult(context);
        }
        
        if(logger.isDebugEnabled()) {
            logger.debug("Update Empty Country Code: Processing of current batch complete.");
            logger.debug("Update Empty Country Code: Successful records count = "+context.getProcessStatistics().getNumberOfSuccessfulRecords());
            logger.debug("Update Empty Country Code: Failure records count ="+context.getProcessStatistics().getNumberOfErrorRecords());
        }

	}
	public LookupService getLookupService() {
		return lookupService;
	}
	public void setLookupService(LookupService lookupService) {
		this.lookupService = lookupService;
	}
	public TransactionTimestampManager getTimestampManager() {
		return timestampManager;
	}
	public void setTimestampManager(TransactionTimestampManager timestampManager) {
		this.timestampManager = timestampManager;
	}

}
