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

// Java classes
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
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;
import gov.va.med.fw.util.StringUtils;

// ESR classes
import gov.va.med.esr.common.model.lookup.ReportFacilityDisplayBy;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.lookup.VOAFormType;
import gov.va.med.esr.common.model.report.ReportFacility;
import gov.va.med.esr.common.model.report.ReportFormType;
import gov.va.med.esr.common.model.report.ReportSetup;
import gov.va.med.esr.common.model.report.ReportParameterSet;
import gov.va.med.esr.common.report.data.CommonCriteria;
import gov.va.med.esr.common.report.data.StandardReportCriteria;

/**
 * EED3 reports DAO.
 *
 * @author Muddaiah Ranga
 */
public class VOA1ReportDataDAOImpl extends AbstractStandardReportDataDAOImpl {

	private static final long serialVersionUID = -5657439440961807171L;
    
	/**
	 * A default constructor
	 */
	public VOA1ReportDataDAOImpl() {
		super();
	}

    /* 
     * @see gov.va.med.fw.report.data.ReportDataDAO#preDataRetrieval(gov.va.med.fw.report.ReportConfiguration)
     */
    public void preDataRetrieval( ReportConfiguration config ) throws ReportDataException {
        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 ) );
           
           // VOA Form Type params
           Set voaFormTypes = parameters.getFormTypes();
           if (voaFormTypes == null || voaFormTypes.isEmpty()) {
               criteria.getCriteria().put(CommonCriteria.VOA_FORM_TYPES, "All");
           } else {
        	   criteria.getCriteria().put(CommonCriteria.VOA_FORM_TYPES, getVoaFormTypeNames(voaFormTypes));
           }
           
           // Can't really return VISN params to report since someone elected to only ever send Sites as criteria
           ReportFacilityDisplayBy facilityDisplayBy = parameters.getFacilityDisplayBy();
           if(facilityDisplayBy == null || StringUtils.isEmpty(facilityDisplayBy.getCode())) {
               //No additional parameters are required to be passed
           } else {    
               if (StringUtils.equals(facilityDisplayBy.getCode(),ReportFacilityDisplayBy.CODE_VISN.getCode())) {
                   Set visns = parameters.getFacilities();                   
                   //When 1 or more VISNs selected
                   if (visns != null && !visns.isEmpty()) {
                	   if (visns.size() > 23)
                           criteria.getCriteria().put(CommonCriteria.VISNS, "All");
                	   else 
                		   criteria.getCriteria().put(CommonCriteria.VISNS, getVisnNames(visns));
                   }
               //When 0, more or all facilities selected
               } else {
                   Set reportFacilities = parameters.getFacilities();
                   if(reportFacilities == null || reportFacilities.isEmpty()) {
                       criteria.getCriteria().put(CommonCriteria.FACILITIES, "All");
                       criteria.getCriteria().put(CommonCriteria.VISNS, "All");
                   } else {
                       criteria.getCriteria().put(CommonCriteria.FACILITIES, this.getFacilitityCodes(reportFacilities));
//                       List visns = getFacilitityIds(parameters.getFacilities());
//                       criteria.getCriteria().put(CommonCriteria.VISNS, this.getVisnCodes(visns));
                   }
               }
           }
        }
    }
    
	/**
	 * @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() );
			}

            Date startDate = parameters.getFromDate();
            if(startDate == null) {
                throw new ReportDataException( "Missing Start Date in report " + config.getReportID() );
            }
            
            Date endDate = parameters.getToDate();
            if(endDate == null) {
                throw new ReportDataException( "Missing End Date in report " + config.getReportID() );
            }
            
            query.setDate(CommonCriteria.START_DATE, startDate);
            query.setDate(CommonCriteria.END_DATE,endDate);
            
            // VOA Form Type params
            Set voaFormTypes = parameters.getFormTypes();
            if (voaFormTypes == null || voaFormTypes.isEmpty()) {
                List dummyVoaFormTypes = new ArrayList();
                dummyVoaFormTypes.add(new Integer(0));
                query.setParameterList( CommonCriteria.VOA_FORM_TYPES, dummyVoaFormTypes);
                query.setString(CommonCriteria.ALL_VOA_FORM_TYPES,"all");
            } else {
                query.setParameterList( CommonCriteria.VOA_FORM_TYPES, this.getVoaFormTypeIds(voaFormTypes));
                query.setString(CommonCriteria.ALL_VOA_FORM_TYPES,"notAll");
            }
            
            ReportFacilityDisplayBy facilityDisplayBy = parameters.getFacilityDisplayBy();
            if(facilityDisplayBy == null || StringUtils.isEmpty(facilityDisplayBy.getCode())) {
                //No additional parameters are required to be passed
            } else {    
                //When 1 or more VISNs selected
                if(StringUtils.equals(facilityDisplayBy.getCode(),ReportFacilityDisplayBy.CODE_VISN.getCode())) {
                    List visns = this.getFacilitityIds(parameters.getFacilities());
                    if(visns != null && !visns.isEmpty()) {
                        query.setParameterList( CommonCriteria.VISNS, visns.toArray() );
                    }
                    //case where novisn is selected
                    else {
                        List facilities = new ArrayList();
                        facilities.add(new Integer(0));
                        query.setParameterList( CommonCriteria.VISNS, facilities);
                    }
                    //NOVISN is selected
                    if (parameters.isNoVISNPresent()){
                        query.setString(CommonCriteria.IS_NO_VISN,CommonCriteria.IS_NO_VISN);
                    }
                    else {
                        query.setString(CommonCriteria.IS_NO_VISN,"VISN");
                    }
                //When 0, more or all facilities selected
                } else {
                    Set reportFacilities = parameters.getFacilities();
                    if(reportFacilities == null || reportFacilities.isEmpty()) {
                        List facilities = new ArrayList();
                        facilities.add(new Integer(0));
                        query.setParameterList( CommonCriteria.FACILITIES, facilities);
                        query.setString(CommonCriteria.IS_ALL,"all");
                    } else {
                        query.setParameterList( CommonCriteria.FACILITIES, this.getFacilitityIds(reportFacilities));
                        query.setString(CommonCriteria.IS_ALL,"notAll");
                    }
                }
            }
		}
		return query;
	}
    
    private List getFacilitityIds(Set facilities) {
        Iterator i = facilities != null ? facilities.iterator() : null;
        ArrayList list = new ArrayList();
        while( i != null && i.hasNext() ) {
            ReportFacility rFacility = (ReportFacility)i.next();
            if(rFacility != null) list.add(((VAFacility)rFacility.getLookup()).getIdentifier());
        }
        return list;
    }
    
    private String getFacilitityCodes(Set facilities) {
        Iterator i = facilities != null ? facilities.iterator() : null;
        StringBuilder list = new StringBuilder();
        while ( i != null && i.hasNext() ) {
            ReportFacility rFacility = (ReportFacility)i.next();
            if (rFacility != null) list.append(((VAFacility)rFacility.getLookup()).getCode());
            if (i.hasNext())
            	list.append(",");
        }
        return list.toString();
    }
    
    private String getVisnNames(Set facilities) {
        Iterator i = facilities != null ? facilities.iterator() : null;
        StringBuilder list = new StringBuilder();
        while ( i != null && i.hasNext() ) {
            ReportFacility rFacility = (ReportFacility)i.next();
            if (rFacility != null) list.append(((VAFacility)rFacility.getLookup()).getName());
            if (i.hasNext())
            	list.append(",");
        }
        return list.toString();
    }
    
    private List getVoaFormTypeIds(Set voaFormTypes) {
        Iterator i = voaFormTypes != null ? voaFormTypes.iterator() : null;
        ArrayList list = new ArrayList();
        while( i != null && i.hasNext() ) {
        	ReportFormType rFormType = (ReportFormType)i.next();
            if(rFormType != null) list.add(((VOAFormType)rFormType.getLookup()).getIdentifier());
        }
        return list;
    }
    
    private String getVoaFormTypeNames(Set voaFormTypes) {
        Iterator i = voaFormTypes != null ? voaFormTypes.iterator() : null;
        StringBuilder list = new StringBuilder();
        while ( i != null && i.hasNext() ) {
            ReportFormType rFormType = (ReportFormType)i.next();
            if (rFormType != null) list.append(((VOAFormType)rFormType.getLookup()).getName());
            if (i.hasNext())
            	list.append(",");
        }
        return list.toString();
    }
}