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

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;

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;

import gov.va.med.esr.common.model.lookup.EnrollmentStatus;
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.report.ReportEnrollmentStatus;
import gov.va.med.esr.common.model.report.ReportFacility;
import gov.va.med.esr.common.model.report.ReportParameterSet;
import gov.va.med.esr.common.model.report.ReportSetup;
import gov.va.med.esr.common.report.data.CommonCriteria;
import gov.va.med.esr.common.report.data.StandardReportCriteria;

/**
 * EED1 Reports Data DAO.
 * 
 * @author Muddaiah Ranga
 *
 */
public class EED1ReportDataDAOImpl extends AbstractStandardReportDataDAOImpl {

    private static final long serialVersionUID = 1178123948624532738L;

    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);
            
            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");
                    }
                }
            }
            
            Set enrollmentStatuses = parameters.getEnrollmentStatuses();
            query.setParameterList( CommonCriteria.ENROLLMENT_STATUSES, this.getEnrollmentStatusIds(enrollmentStatuses));
        }
        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 List getEnrollmentStatusIds(Set reportEnrollmentStatus) {
        ArrayList list = new ArrayList();
        if(reportEnrollmentStatus == null || reportEnrollmentStatus.isEmpty()) {
            Set pendingEs = EnrollmentStatus.getPendingEnrollmentStatuses();
            if(pendingEs != null) {
                for(Iterator iter = pendingEs.iterator(); iter.hasNext();) {
                    list.add((String)iter.next());
                }
            }
        } else {
            Iterator i = reportEnrollmentStatus != null ? reportEnrollmentStatus.iterator() : null;
            while( i != null && i.hasNext() ) {
                ReportEnrollmentStatus rEnrollmentStatus = (ReportEnrollmentStatus)i.next();
                if(rEnrollmentStatus != null) list.add(((EnrollmentStatus)rEnrollmentStatus.getLookup()).getCode());
            }
        }
        return list;
    }
}