package gov.va.med.esr.service.impl;

// Java Classes
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

// Library Classes
import org.quartz.Trigger;
import org.quartz.SchedulerException;

// Framework Classes
import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.pagination.SearchQueryInfo;

// ESR Classes
import gov.va.med.esr.common.model.report.ReportSetupLite;
import gov.va.med.esr.service.ScheduledReportService;
import gov.va.med.esr.service.ReportFilterSearchQueryInfo;

/**
 * Service to retrieve a filtered list of scheduled reports.
 *
 * @author DNS   CHENJ2
 * @author Andrew Pach
 */
public class ScheduledReportServiceImpl extends StandardReportServiceImpl implements ScheduledReportService
{
    private static final long serialVersionUID = -6367870366143211518L;

    /**
     * Search Scheduled reports using filter parameters provided.
     *
     * @param searchQueryInfo the search query information.
     *
     * @return the list of ReportSetupLite objects.
     * @throws ServiceException if any problems were encountered.
     */
    public List search(SearchQueryInfo searchQueryInfo) throws ServiceException
    {
        // Initialize the list of return values
        List setups = new ArrayList();

        try
        {
            // First filter against the entered search criteria at thd DAO level.
            ReportFilterSearchQueryInfo searchCriteria = (ReportFilterSearchQueryInfo)searchQueryInfo;
            List rptItems = getReportDAO().searchScheduledReports(searchCriteria);

            // Then filter against Trigger.nextFireTime for the next fire time since this is stored
            // in Quartz and not in the database
            if (rptItems != null && !rptItems.isEmpty())
            {
                // Iterate through each returned ReportSetupLite object
                for (Iterator iter = rptItems.iterator(); iter.hasNext();)
                {
                    ReportSetupLite setup = (ReportSetupLite)iter.next();

                    // skip over and return record if the setup user is null!
                    if (setup.getSetupUser() == null) {
                    	setups.add(setup);
                    }
                    else {
	                    // Get the name of the trigger
	                    String triggerName = SCHEDULED_JOBS + "." + setup.getSetupUser().getName() + "."
	                        + setup.getReport().getCode() + "." + setup.getEntityKey().getKeyValueAsString();
	                    try
	                    {
	                        // Get the scheduled trigger
	                        Trigger trigger = getSchedulingService().getTrigger(triggerName, ESR_COMMON_TRIGGERS);
	
	                        //  Get the next fire time
	                        Date nextFireTime = trigger != null ? trigger.getNextFireTime() : null;
	
	                        // Only add the report setup to the return list if the date filter passed
	                        if ((nextFireTime == null) || (searchCriteria.getDateFrom() == null ||
	                            !nextFireTime.before(searchCriteria.getDateFrom())) &&
	                            (searchCriteria.getDateTo() == null || !nextFireTime.after(searchCriteria.getDateTo())))
	                        {
	                            // Set the next fire time on the returned report setup and add it to the returned list
	                            setup.setDateToGenerate(nextFireTime);
	                            setups.add(setup);
	                        }
	                    }
	                    catch (SchedulerException scEx)
	                    {
	                        throw new ServiceException("Error getting trigger with Id: " + triggerName, scEx);
	                    }
                    }
                }
            }
        }
        catch (DAOException e)
        {
            throw new ServiceException("ScheduledReports Search Failed.  searchQueryInfo: " + searchQueryInfo, e);
        }
        //Set the total entries to actual value to display pagination info correctly.
        searchQueryInfo.setTotalNumberOfEntries(setups.size());
        // Return the list of filtered ReportSetupLite objects.
        return setups;
    }
}
