package gov.va.med.esr.common.persistent.comms.hibernate;

import gov.va.med.esr.common.model.comms.HandbookBatchRequestStatistics;
import gov.va.med.esr.common.model.comms.HandbookBatchStatistics;
import gov.va.med.esr.common.model.comms.HandbookStatsColumnInfo;
import gov.va.med.esr.common.model.lookup.HandBookRequestStatusType;
import gov.va.med.esr.common.persistent.comms.HandbookBatchStatisticsDAO;
import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.persistent.hibernate.AbstractDAOImpl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.springframework.dao.DataAccessException;

public class HandbookBatchStatisticsDAOImpl extends  AbstractDAOImpl implements HandbookBatchStatisticsDAO{

	/**
	 * 
	 */
	private static final long serialVersionUID = 7438726047987826137L;
	private static final String QRY_HANDBOOK_BATCH_STAT_BATCHINFO = "handBookBatchRequest_statistics_batchInfo";
	private static final String QRY_HANDBOOK_BATCH_STAT_SENTTOCMS = "handBookBatchRequest_statistics_sentToCMS";
	private static final String QRY_HANDBOOK_BATCH_STAT_REJ_HEC = "handBookBatchRequest_statistics_rejectedByHEC";
	private static final String QRY_HANDBOOK_BATCH_STAT_MAILEDBYCMS = "handBookBatchRequest_statistics_mailedByCMS";
	private static final String QRY_HANDBOOK_BATCH_STAT_ONLINE = "handBookBatchRequest_statistics_onLine";
	private static final String QRY_HANDBOOK_BATCH_STAT_ERRCMS = "handBookBatchRequest_statistics_erroredByCMS";
	private static final String QRY_HANDBOOK_BATCH_STAT_CODE1REJ = "handBookBatchRequest_statistics_code1Reject";
	private static final String QRY_HANDBOOK_BATCH_STAT_RETUSPS = "handBookBatchRequest_statistics_returnedByUSPS";
	private static final String QRY_HANDBOOK_BATCH_STAT_VBR_HB = "handBookBatchRequest_statistics_handbooksInVBR";
	private static final String QRY_HANDBOOK_BATCH_STAT_VBR_BAG = "handBookBatchRequest_statistics_benefitsAtAGlanceInVBR";

	private static final HandbookStatsColumnInfo[] queryToCountIndexMapList = {
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_REJ_HEC, HandbookBatchStatistics.REJ_BY_HEC),
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_SENTTOCMS, HandbookBatchStatistics.SENT_TO_CMS),		
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_MAILEDBYCMS, HandbookBatchStatistics.MAILED_BY_CMS),
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_ONLINE, HandbookBatchStatistics.ONLINE),
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_VBR_HB, HandbookBatchStatistics.HB_IN_VBR),
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_VBR_BAG, HandbookBatchStatistics.BAG_IN_VBR),
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_ERRCMS,  HandbookBatchStatistics.ERRORED_BY_CMS),
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_CODE1REJ,  HandbookBatchStatistics.CODE_1_REJECT),
		new HandbookStatsColumnInfo(QRY_HANDBOOK_BATCH_STAT_RETUSPS, HandbookBatchStatistics.RETURNED_BY_USPS)
	};
	
	public List<HandbookBatchRequestStatistics> getHandbookBatchRequestStatistics(Date releaseDate) throws DAOException {
		
		List<HandbookBatchRequestStatistics> requestStats = new ArrayList<HandbookBatchRequestStatistics>();
        
		// First fetch the basic batch request data based on release date criteria 
		getBatchRequestInfo(requestStats, releaseDate);
		
		// Next get the list of completed batch Ids
		List<BigDecimal> completedBatchIds = getCompletedBatchIds(requestStats);
		
		// only get statistis counts for copmleted batches
		if (!completedBatchIds.isEmpty()) {
			getBatchStatistics(requestStats, completedBatchIds);
			getTotalCounts(requestStats);
		}
		
        return requestStats; 
    }  
	
	private void getBatchRequestInfo(List<HandbookBatchRequestStatistics> requestStats, Date releaseDate) 
		throws DAOException {
		try {   
			String[] batchIdParamFields = {"releaseDate"};
			Object[] batchIdParamValues = {releaseDate} ;		
			List results = super.getHibernateTemplate().findByNamedQueryAndNamedParam(QRY_HANDBOOK_BATCH_STAT_BATCHINFO,
		        		  batchIdParamFields, batchIdParamValues);
			
			for (Iterator i=results.iterator(); i.hasNext();) {
				Object[] data = (Object[])i.next();
				HandbookBatchRequestStatistics stat = buildBatchRequestStat(data); 
				requestStats.add(stat);
			}
		} catch (DataAccessException e) {
            throw new DAOException("Failed to get handbook statistics by release date", e);
        }
	}
	
	private HandbookBatchRequestStatistics buildBatchRequestStat(Object[] data) {
		
		HandbookBatchRequestStatistics stat = new HandbookBatchRequestStatistics(); 
		stat.setBatchRequestId((BigDecimal)data[0]);
		stat.setBatchRequestStatus((String)data[1]);
		stat.setRequestNote((String)data[2]);
		stat.setMaxPerJobNumber((Integer)data[3]);
		stat.setBatchReleaseSize((Integer)data[4]);
		return stat;
	}
	                                                                             
	private List<BigDecimal> getCompletedBatchIds(List<HandbookBatchRequestStatistics> requestStats) {
		List<BigDecimal> completedIds = new ArrayList<BigDecimal>();
		for (Iterator<HandbookBatchRequestStatistics> i=requestStats.iterator(); i.hasNext();) {
			HandbookBatchRequestStatistics stat = i.next();
			if (HandBookRequestStatusType.COMPLETED.getCode().equals(stat.getBatchRequestStatus())) {
				completedIds.add(stat.getBatchRequestId());
			}
		}
		return completedIds;
	}
	
	private void getBatchStatistics(List<HandbookBatchRequestStatistics> requestStats, List<BigDecimal> batchIds) {

		// go through all the queries, execute each, set the result count into the proper count value
		for (HandbookStatsColumnInfo queryCountIndexSet : queryToCountIndexMapList) {
			
			List results = super.getHibernateTemplate().findByNamedQueryAndNamedParam(queryCountIndexSet.getQueryName(),
					"batchRequestIds", batchIds);

			for (Iterator i=results.iterator(); i.hasNext();) {
				Object[] data = (Object[])i.next();
				BigDecimal id = (BigDecimal)data[0];
				Integer count = (Integer)data[1];
				
				// only do count for completed requests
				HandbookBatchRequestStatistics stat = findStatById(requestStats, id);
				if (stat != null) {
					stat.setCounts(queryCountIndexSet.getCountIndex(), count);
				}
			}
		}
	}
	
	private HandbookBatchRequestStatistics findStatById(List<HandbookBatchRequestStatistics> requestStats, BigDecimal requestId) {
		
		if (requestId != null) {
			for (HandbookBatchRequestStatistics stat : requestStats) {
				if (requestId.equals(stat.getBatchRequestId())) {
					return stat;
				}
			}
		}
		return null;
	}
	
	private void getTotalCounts(List<HandbookBatchRequestStatistics> requestStats) {
		HandbookBatchRequestStatistics totalStats = new HandbookBatchRequestStatistics();
		totalStats.setRequestNote("Total Count:");
		
		for (HandbookBatchRequestStatistics stat: requestStats) {
			for (HandbookStatsColumnInfo queryCountIndex : queryToCountIndexMapList) {
				int index = queryCountIndex.getCountIndex();
				totalStats.setCounts(index, totalStats.getCounts(index)+stat.getCounts(index));
			}
			totalStats.setMaxPerJobNumber(totalStats.getMaxPerJobNumber()+stat.getMaxPerJobNumber());
			totalStats.setBatchReleaseSize(totalStats.getBatchReleaseSize()+stat.getBatchReleaseSize());
			
		}
		requestStats.add(totalStats);
	}
	
public List<Date> getHandbookBatchFileProcessDateList() throws DAOException {
		
		return null;
    }  

}



