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

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.context.MessageSource;

import gov.va.med.esr.common.report.data.CommonExtractFileCriteria;
import gov.va.med.esr.common.report.data.MainFileCriteria;
import gov.va.med.esr.service.CommsEmailBulletinService;
import gov.va.med.esr.service.StandardReportService;
import gov.va.med.esr.service.trigger.BulletinTrigger;
import gov.va.med.fw.batchprocess.DataProcessCompletedHandler;
import gov.va.med.fw.batchprocess.DataProcessExecutionContext;
import gov.va.med.fw.security.SecurityContextHelper;
import gov.va.med.fw.security.UserPrincipal;
import gov.va.med.fw.service.AbstractComponent;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.StringUtils;

/**
 * Process Completed handler for OPP Extract process.
 * 
 * Calls the report service to generate all the reports
 * 
 * @author Rajiv Patnaik Created on Mar 28, 2006
 * @version 1.0
 * 
 * Copyright © 2006 VHA. All rights reserved
 */
public class OPPExtractProcessCompletedHandler extends AbstractComponent
        implements DataProcessCompletedHandler
{

    private StandardReportService standardReportService;
    private CommsEmailBulletinService bulletinService;    
    private MessageSource messageSource;

    /**
     * @return Returns the standardReportService.
     */
    public StandardReportService getStandardReportService()
    {
        return standardReportService;
    }

    /**
     * @param standardReportService
     *            The standardReportService to set.
     */
    public void setStandardReportService(
            StandardReportService standardReportService)
    {
        this.standardReportService = standardReportService;
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.fw.batchprocess.DataProcessCompletedHandler#dataProcessingComplete(gov.va.med.fw.batchprocess.DataProcessExecutionContext)
     */
    public void dataProcessingComplete(DataProcessExecutionContext context)
    {

        OPPExtractProcessStatistics statistics = (OPPExtractProcessStatistics) context
                .getProcessStatistics();
        
        //Generate Main File report
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_MAIN_EXTRACT, statistics.getProcessName()))
	        generateMainFileExtractReport(statistics);        

        // No longer needed as report is not useful
        /*
        //Generate report for CD Condition Data
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_CD_CONDITION, statistics.getProcessName()))
	        generateCommonExtractReport(CommonExtractFileCriteria.CDCONDITION_FILE,
	                statistics.getNumberOfCDConditionFileRecords());

        //Generate report for CD Diagnosis data
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_CD_DIAGNOSIS, statistics.getProcessName()))
	        generateCommonExtractReport(CommonExtractFileCriteria.CDDIAGNOSIS_FILE,
	                statistics.getNumberOfCDDiagnosisFileRecords());
        
        //Write CD Procedure
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_CD_PROCEDURE, statistics.getProcessName()))
	        generateCommonExtractReport(CommonExtractFileCriteria.CDPROCEDURE_FILE,
	                statistics.getNumberOfCDProcedureFileRecords());        

        //Generate report for CD Descriptor Data
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_CD_DESCRIPTOR, statistics.getProcessName()))
	        generateCommonExtractReport(CommonExtractFileCriteria.CDDESCRIPTOR_FILE,
	                statistics.getNumberOfCDDescriptorFileRecords()); */

         //Generate report for Eligibility data
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_ELIGIBILITY, statistics.getProcessName()))
	        generateCommonExtractReport(CommonExtractFileCriteria.ELIGIBILITY_FILE,
	                statistics.getNumberOfEligibilityFileRecords());
        
        //Generate report for Period Of Service data
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_PERIOD_OF_SERVICE, statistics.getProcessName()))
	        generateCommonExtractReport(
	                CommonExtractFileCriteria.PERIODOFSERVICE_FILE, statistics
	                        .getNumberOfPeriodOfServiceFileRecords());

        //Generate report for Rated disabilities data
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_RATED_DISABILITY, statistics.getProcessName()))
	        generateCommonExtractReport(
	                CommonExtractFileCriteria.RATEDDISABILITIES_FILE, statistics
	                        .getNumberOfRatedDisabilitiesFileRecords());
    
        //Generate report for oef/oif (combat episodes data)
        if(StringUtils.equals(OPPExtractConstants.PROCESS_TYPE_COMBAT_EPISODE, statistics.getProcessName()))
	        generateCommonExtractReport(
	                CommonExtractFileCriteria.COMBATEPISODES_FILE, statistics
	                        .getNumberOfCombatEpisodeFileRecords());
        
        // send bulletin
        if(bulletinService != null) {
        	try {
	            Map bulletinData = new HashMap();
	            bulletinData.put("StartTime", statistics.getProcessingStartDate());
	            bulletinData.put("EndTime", new Date());
	            bulletinService.sendEmailBulletin(BulletinTrigger.DataType.OPP_EXTRACT_COMPLETED,
	                    bulletinData, null);
        	} catch(ServiceException e) {
                throw new RuntimeException(
                        "Exception while handling the completion of OPP processing", e);        		
        	}
        }                    
    }
    
    private void generateMainFileExtractReport(OPPExtractProcessStatistics statistics)
    {
		MainFileCriteria criteria = new MainFileCriteria(getMessageSource());
		criteria.setRecords( new Integer( statistics.getNumberOfMainFileRecords()) );
		criteria.setAutoEnrolledRecords( new Integer(statistics.getNumberOfAutoEnrolledRecords()) );
		criteria.setCancelledDeclinedEnrollees( new Integer(statistics.getNumberOfCanceledDeclinedEnrollees()) );
		criteria.setDeceasedBeneficiaries( new Integer(statistics.getNumberOfDeceasedBeneficiaries()) );
		criteria.setIneligibleBeneficiaries( new Integer(statistics.getNumberOfIneligibleEnrolees()) );
		criteria.setInsurances( new Integer(statistics.getNumberOfActiveHealthInsuranceRecords()) );
		criteria.setOfficialEnrollees( new Integer(statistics.getNumberOfOfficialEnrollees()) );
		criteria.setRequiredMeansTests( new Integer(statistics.getNumberOfPendingMeansTestRecords()) );
		criteria.setTotalEnrollees( new Integer(statistics.getNumberOfTotalEnrollees()) );
		criteria.setUnOfficialEnrollees( new Integer(statistics.getNumberOfUnOfficialEnrollees()) );        
		
        logger.info("Calling Report Service to generate report for Main File Extract ");
		
		generateReport(criteria);
    }

    /**
     * @param criteriaType
     * @param countOfRecords
     */
    private void generateCommonExtractReport(
            CommonExtractFileCriteria.Type criteriaType, int countOfRecords)
    {
        CommonExtractFileCriteria criteria = new CommonExtractFileCriteria(
                criteriaType, getMessageSource());
        
        criteria.setRecords(new Integer(countOfRecords));
        
        logger.info("Calling Report Service to generate report for process "
                + criteriaType.getName());
        
        generateReport(criteria);
    }

    /**
     * @param criteria
     * @throws ServiceException
     */
    private void generateReport(CommonExtractFileCriteria criteria) 
    {
        try
        {
            UserPrincipal user = SecurityContextHelper.getSecurityContext()
                    .getUserPrincipal();
            logger.info("OPP Extract generating reports logged in as " + SecurityContextHelper.getUserName(user));
            
            this.getStandardReportService().generateOPPReport(user, criteria);
        } catch (Exception e)
        { 
            String errorMessage = "Could not generate report for OPP Extract process "
                            + criteria ;
            
            logger.error(errorMessage, e);            
            throw new RuntimeException(errorMessage, e);
        }
    }

    /**
     * @return Returns the messageSource.
     */
    public MessageSource getMessageSource()
    {
        return messageSource;
    }
    /**
     * @param messageSource The messageSource to set.
     */
    public void setMessageSource(MessageSource messageSource)
    {
        this.messageSource = messageSource;
    }

	/**
	 * @return Returns the bulletinService.
	 */
	public CommsEmailBulletinService getBulletinService() {
		return bulletinService;
	}

	/**
	 * @param bulletinService The bulletinService to set.
	 */
	public void setBulletinService(CommsEmailBulletinService bulletinService) {
		this.bulletinService = bulletinService;
	}
}