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

// Java classes
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;

// Library classes
import org.hibernate.Query;
import org.hibernate.Session;

// Framework classes
import gov.va.med.fw.report.ReportConfiguration;
import gov.va.med.fw.report.data.QueryCriteria;
import gov.va.med.fw.report.data.ReportDataException;

// ESR classes
import gov.va.med.esr.common.model.report.ReportFacility;
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.ReportBadAddressReason;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.report.data.CommonCriteria;
import gov.va.med.esr.common.report.data.StandardReportCriteria;


/**
 * Provides methods to build a HQL statemenets for retrieving report data.  This interface is 
 * intented to retrieve report data for all ESR standard reports related to address info.
 *
 * Project: Common</br>
 * Created on: 2:28:16 PM </br>
 *
 * @author DNS   LEV
 */
public class AddressReportDataDAOImpl extends AbstractStandardReportDataDAOImpl {

	/**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = -5657439440961807171L;

	/**
	 * A default constructor
	 */
	public AddressReportDataDAOImpl() {
		super();
	}
	
public void preDataRetrieval(ReportConfiguration config)
	throws ReportDataException {
	super.preDataRetrieval(config);
	QueryCriteria reportCriteria = config.getQueryCriteria();
	
		if (reportCriteria instanceof StandardReportCriteria) {
			StandardReportCriteria criteria = (StandardReportCriteria) reportCriteria;
			ReportSetup setup = criteria.getReportSetup();
			ReportParameterSet parameters = setup != null ? setup
					.getParameterSet() : null;
			if (parameters == null) {
				throw new ReportDataException(
						"Missing report parameters in report "
								+ config.getReportID());
			}
	
			criteria.setStartDate(this.getDate(config, true));
			criteria.setEndDate(this.getDate(config, false));
			
			String visnNames = "";
			Set visns = parameters.getFacilities();
			if (visns != null && !visns.isEmpty()) {						
				ArrayList visnVistaNameList = this.getVistaNameList(parameters.getFacilities());
				visnNames = this.getItemsAsString(visnVistaNameList);
				criteria.addCriterion(CommonCriteria.VISNS, visnNames);	
			}							
			else {
				criteria.addCriterion(CommonCriteria.VISNS, "NO VISN");
			}
			
	        if (parameters.getFileType() != null) {
	        	 criteria.setFileType(parameters.getFileType().getCode());
	         }
		}
	}	
 
	private ArrayList getVistaNameList(Set facilities) {
		Iterator i = facilities != null ? facilities.iterator() : null;
		ArrayList vistaNameList = new ArrayList();
		while (i != null && i.hasNext()) {
			ReportFacility rFacility = (ReportFacility) i.next();
			if (rFacility != null && rFacility.getLookup() != null) {
				vistaNameList.add(rFacility.getFacility().getDescription());
			}
		}
		return vistaNameList;
	}
	
	private String getItemsAsString(ArrayList facilities) {
		Iterator i = facilities != null ? facilities.iterator() : null;
		StringBuffer sBuf = new StringBuffer();
		if (i != null && i.hasNext()) {
			String rFacility = (String) i.next();
			sBuf.append(rFacility);
		}
		
		while (i != null && i.hasNext()) {
			sBuf.append(", ");
			String rFacility = (String) i.next();
			sBuf.append(rFacility);
		}
		return sBuf.toString();
	}

	/**
	 * @see gov.va.med.fw.report.data.hibernate.HibernateReportDataDAO#buildQuery(gov.va.med.fw.report.ReportConfiguration)
	 */
	protected Query buildQuery( ReportConfiguration config,Session session) throws ReportDataException {
		
		QueryCriteria reportCriteria = config.getQueryCriteria();
		Query query = null;

		if( reportCriteria instanceof StandardReportCriteria ) {

			// Get a named query
			query = this.getNamedQuery(session);
			
			// Get a criteria
			StandardReportCriteria criteria = (StandardReportCriteria)reportCriteria;
			ReportSetup setup = criteria.getReportSetup();
			ReportParameterSet parameters = setup != null ? setup.getParameterSet() : null;
			if( parameters == null ) {
				throw new ReportDataException("Missing report parameters in report " + config.getReportID() );
			}
			 List visns = new ArrayList ();
			 Set facilities = parameters.getFacilities();            
	    		if(facilities != null && !facilities.isEmpty()) {            	
	    			for (Iterator i=facilities.iterator(); i.hasNext();){
	    				VAFacility facility = ((ReportFacility)i.next()).getFacility();
	    				visns.add(facility.getIdentifier());
	    			}
	            } 
			// Populate a query with input data
			Set reasons = parameters.getBadAddressReasons();
			Iterator i = reasons != null ? reasons.iterator() : null;
			Collection list = new ArrayList();
			while( i != null && i.hasNext() ) {
				ReportBadAddressReason reason = (ReportBadAddressReason)i.next();
				list.add( reason.getLookup().getCode() );
			}
			Object[] codes = list.toArray(); 
			if( codes == null || codes.length <= 0 ) {
				throw new ReportDataException( "Missing address reason codes in report " + config.getReportID() );
			}
			if(visns.isEmpty()) {
				visns.add(new BigDecimal(-1));
				//throw new ReportDataException( "Missing VISN in report " + config.getReportID() );
			}
			query.setParameterList(CommonCriteria.VISNS, visns);
			query.setDate( CommonCriteria.START_DATE, parameters.getFromDate() );
			query.setDate( CommonCriteria.END_DATE, parameters.getToDate() );
			query.setParameterList( CommonCriteria.BAD_ADDRESS_REASON, codes );
			
            if (parameters.isNoVISNPresent()){
                query.setString("noVISN", "noVISN");
            }
            else {
                query.setString("noVISN","VISN");
            }
		}
		return query;
	}	
}