/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
// Package
package gov.va.med.esr.common.report.data;

// Framework classes
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;

import org.apache.commons.lang.Validate;

import gov.va.med.esr.common.model.lookup.ReportFormat;
import gov.va.med.esr.common.model.report.ReportParameterSet;
import gov.va.med.fw.report.ConfigurableReportBuilder;
import gov.va.med.fw.report.ReportConfiguration;
import gov.va.med.fw.report.ReportException;
import gov.va.med.fw.report.data.QueryCriteria;
import gov.va.med.fw.report.data.ReportData;
import gov.va.med.fw.report.data.ReportDataService;
import gov.va.med.fw.report.jasperreport.data.JasperReportData;
import gov.va.med.fw.util.StringUtils;


/**
 * This class allows to use multiple data source for a report.
 *
 * Project: Framework</br>
 * Created on: 4:59:46 PM </br>
 *
 * @author DNS   kullav
 */
public class CompositeReportBuilder extends ConfigurableReportBuilder {

	private static final long serialVersionUID = 1325536722208589025L;
	
	private Map queryNames = null;
	
	private Map requiredDataSources = null;
	
	/**
	 * Map of Report ID to list of query names.
	 * @param queryNames
	 */
	public void setQueryNames(Map queryNames)
	{
		this.queryNames=queryNames;
	}
	
	/**
	 * Map of Report ID to master report requires data source or not.
	 * @param requiredDataSources
	 */
	public void setRequiredDataSources( Map requiredDataSources )
	{
		this.requiredDataSources=requiredDataSources;
	}
	
    /**
     * This method gets data source for each quary and sets in 
     * config.setResourceMapping except for first data source
	 * @param configuration
	 * @return
	 * @throws ReportException
	 */
	protected ReportData doRequestData( ReportConfiguration configuration ) throws ReportException {
		
		// Get a report service and a report name
		ReportDataService service = this.getReportDataService( configuration );
		QueryCriteria criteria = configuration.getQueryCriteria();
	    StandardReportCriteria reportCriteria = criteria instanceof StandardReportCriteria ? (StandardReportCriteria)criteria : null;
	    ReportParameterSet paramsSet=(reportCriteria != null && reportCriteria.getReportSetup() != null) ? reportCriteria.getReportSetup().getParameterSet():null;
	    ReportFormat format=(paramsSet != null && paramsSet.getReportFormat() != null) ? paramsSet.getReportFormat():null;
		StringBuffer reportName=new StringBuffer();
		reportName.append(configuration.getReportName());
		//Append format type to report name.
		if(format!=null&& format.getDescription()!=null)
		{
			reportName.append(".").append(StringUtils.deleteWhitespace(format.getDescription()));			
		}		
		//Check master report requires datasource.
		Object tmp = requiredDataSources.get( reportName.toString() );		
		String flag=tmp!=null && tmp.equals("true")?(String)tmp:"false";
		
		boolean dataforMasterReport = new Boolean(flag).booleanValue();
		//Init to empty data source.
		ReportData data = new JasperReportData( new ArrayList() );
		
		//  Get data for reports
		tmp = this.queryNames.get( reportName.toString() );
		List subReports = tmp instanceof List ? (List)tmp : null;
		int totalOfReports = (subReports != null) ? subReports.size() : 0;
		
		// Loop through sub reports to get a list of queries
		for(int i=0; i<totalOfReports; i++ ) {
			String queryName = null;
			if (subReports != null) {
				queryName = subReports.get( i ).toString();
			} 
			try {
				ReportConfiguration reportConfig = new ReportConfiguration( queryName, 
						   configuration.getReportID(),
						   configuration.getReportOutputType(),
						   configuration.getReportOutputName() );
						reportConfig.setQueryCriteria( configuration.getQueryCriteria() );	
						reportConfig.setReportUser( configuration.getReportUser() );
						reportConfig.setResourceMapping( configuration.getResourceMapping() );
				reportConfig.setReportTitle(configuration.getReportTitle());
						// If master report requires data source get it.
				if(dataforMasterReport && i==0)
				{					
					data=service.requestReportData( reportConfig );
				}
				else
				{	// Get data source for sub reports.			
					
					ReportData subReportData = service.requestReportData( reportConfig );
					if( subReportData != null && subReportData instanceof JasperReportData ) {
						configuration.addResourceMapping( queryName, ((JasperReportData)subReportData).getJasperDataSource() );
					}
				}
			}
			catch( IOException e ) {
				throw new ReportException( "Failed to create a report configuration for a subreport", e );
			}
		}
		return data;
	}
  	/**
	 * A default constructor
	 */
	public CompositeReportBuilder() {
		super();
	}
	
	
	/**
	 * @see gov.va.med.fw.service.AbstractComponent#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		super.afterPropertiesSet();
		Validate.notNull( this.queryNames, "A queryNames must be configured" );
		Validate.notNull( this.requiredDataSources, "A requiredDataSources must be configured" );
	}		
}