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

// Java classes
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.io.IOException;
import java.util.HashMap;

// framework 

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.ReportDataService;
import gov.va.med.fw.report.ReportExporter;
import gov.va.med.fw.report.ReportTemplate;
import gov.va.med.fw.service.ServiceException;

// esr
import gov.va.med.esr.common.model.report.ReportSetup;
import gov.va.med.esr.common.model.report.ReportParameterSet;
import gov.va.med.esr.common.model.report.ReportEEDWeeklyReportType;
import gov.va.med.esr.common.model.lookup.ReportEEDWeeklyType;
import gov.va.med.esr.common.rule.service.MergeRuleService;

/**
 * @author DNS   LEV
 *
 */
public class WeeklyReportBuilder extends ConfigurableReportBuilder {

   /**
    * An instance of serialVersionUID
    */
   private static final long serialVersionUID = 3052123366601812768L;
   
   private MergeRuleService mergeRuleService=null;
	

   /**
    * A default constructor
    */
   public WeeklyReportBuilder() {
      super();
   }

   
	 /**
	   * @param serivce The MergeRuleService to set
	   */
	public void setMergeRuleService( MergeRuleService mergeRuleService ) {
	  this.mergeRuleService = mergeRuleService;
	}
   /**
    * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
    */
   public void afterPropertiesSet() throws Exception {
	  
      // Overrides the super method to do nothing here
      // because we don't need to configure dataservices and templates
      // super.afterPropertiesSet();
   }

   /**
    * @see gov.va.med.fw.report.ReportBuilder#buildReport(gov.va.med.fw.report.ReportConfiguration)
    */
   public void buildReport( ReportConfiguration configuration ) throws ReportException {
	      
	      // Extract data from a report configuration
	      QueryCriteria criteria = configuration.getQueryCriteria();
	      StandardReportCriteria reportCriteria = criteria instanceof StandardReportCriteria ? (StandardReportCriteria)criteria : null;
	      ReportSetup reportSetup = reportCriteria != null ? reportCriteria.getReportSetup() : null;
	      ReportParameterSet params = (reportSetup != null) ? reportSetup.getParameterSet() : null;
	      Set list = (params != null) ? params.getReportEEDWeeklyReportTypes() : null;
	    
	      if (list != null) {
		      for( Iterator i=list.iterator(); i.hasNext(); ) {
		    	  
		         ReportEEDWeeklyReportType report_type = (ReportEEDWeeklyReportType)i.next();
		         ReportSetup reportSetupCopy=getReportSetupCopy(reportSetup);
		         removeOtherReportEEDWeeklyReportTypes(reportSetupCopy,report_type);
		          String type = ReportEEDWeeklyType.Code.getByCode( report_type.getReportEEDWeeklyType().getCode() ).getAlias();
	
		         // Gets a report data service and template for each specific EEDB report type
		         ReportDataService service = this.getReportDataService( type + DATA_SERVICE_TAG);
		         ReportTemplate template = this.getReportTemplate( type + REPORT_TEMPLATE_TAG );
		         
		         // Export each EED report type
		         ReportExporter exporter = this.getReportExporter( configuration.getReportOutputType() );
		         
		         // Create individual report configuration for each EED 8's sub report
		         try {
		            // create a sub report's criteria
		        	if (reportCriteria != null && reportCriteria.getCriteria() != null) {
			            StandardReportCriteria sub_criteria = new StandardReportCriteria( new HashMap( reportCriteria.getCriteria() ) );
			            sub_criteria.setReportSetup(reportSetupCopy);
			            sub_criteria.setSubReportName( type );
			            
			            // create a sub report's configuration
			            StringBuffer output = new StringBuffer( (reportSetup != null && reportSetup.getReport() != null) ?  reportSetup.getReport().getCode() : "" );
			            output.append( " - " )
			                  .append( type )
			                  .append( "." )
			                  .append( configuration.getReportOutputType().getAlias().toLowerCase() );
			            
			            ReportConfiguration config = new ReportConfiguration( configuration.getReportName(), 
			                                                                  configuration.getReportID(),
			                                                                  configuration.getReportOutputType(),
			                                                                  output.toString() );
			            config.setReportTitle(configuration.getReportTitle());
			            config.setReportUser( configuration.getReportUser() );
			            config.setResourceMapping( sub_criteria.getCriteria() );
			            config.setQueryCriteria( sub_criteria );
			            
			            exporter.exportReport( config, service.requestReportData( config ), template );
			        	}
		         }
		         catch( IOException e ) {
		            // Failed to create individual report configuration
		            if( logger.isInfoEnabled() ) {
		               logger.info( "Failed to create individual report configuration", e );
		            }
		            throw new ReportException( "Failed to create individual report configuration", e );
		         }
		      }
	      }
	   }  
   
	
	/**
	 * This method removes all other ReportEEDWeeklyReportTypes except the passed ReportEEDWeeklyReportType
	 * @param reportSetup
	 * @param eedType
	 */
   protected void removeOtherReportEEDWeeklyReportTypes(ReportSetup reportSetup, ReportEEDWeeklyReportType eedType)
	{
		ReportEEDWeeklyReportType reportType=null;
		for(Iterator it=reportSetup.getParameterSet().getReportEEDWeeklyReportTypes().iterator();it.hasNext();)
		{
			ReportEEDWeeklyReportType eedReportType=(ReportEEDWeeklyReportType)it.next();
			if(eedReportType.getReportEEDWeeklyType().getIdentifier().equals(eedType.getReportEEDWeeklyType().getIdentifier()) )
			{
				reportType=eedReportType;
				break;
			}
		}
		reportSetup.getParameterSet().removeAllReportEEDWeeklyReportTypes();
		reportSetup.getParameterSet().addReportEEDWeeklyReportType(reportType);		
	}
	
	/**
	 * This method returns copy of getReportSetup.
	 * @param config
	 * @return
	 * @throws ReportException
	 */
	protected ReportSetup getReportSetupCopy(ReportSetup reportSetup)
	throws ReportException
	{
		ReportSetup newReportSetup=null;
	    if(reportSetup!=null)
	    {		    
			newReportSetup=new ReportSetup();
			try{
				this.mergeRuleService.mergeReportSetup(reportSetup, newReportSetup);
			}
			catch( ServiceException e ) {
				e.printStackTrace();
				throw new ReportException( "Failed to merge report setup", e );
				
			}
	    }
	    return newReportSetup;
	}
}