// Package 
package gov.va.med.esr.ui.report.action;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.lookup.ReportType;
import gov.va.med.esr.common.model.lookup.StandardReport;
import gov.va.med.esr.service.ReportFilter;
import gov.va.med.esr.service.ReportStatus;
import gov.va.med.esr.service.UnknownLookupCodeException;
import gov.va.med.esr.service.UnknownLookupTypeException;
import gov.va.med.esr.ui.ApplicationConstants;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.persistent.NoRecordFoundException;
import gov.va.med.fw.report.ReportException;
import gov.va.med.fw.report.ReportExportedType;
import gov.va.med.fw.ui.struts.ValueListActionUtils;
import gov.va.med.fw.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.mlw.vlh.ValueList;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

/**
 * Action for completed reports.
 *
 * @author Andrew Pach
 * @version 3.0
 */
public class CompletedReportsAction extends ReportFilterAction
{
    /**
     * Gets the value list table Id.
     *
     * @return the table id.
     */
    public String getTableId()
    {
        return CMP_REPORT_TABLE_ID;
    }

    /**
     * Gets the value list adapter.
     *
     * @return the adapter.
     */
    public String getValueListAdapter()
    {
        return CMP_REPORTS_VALUE_LIST_ADAPTER;
    }
    
    /**
     * Displays the report data.
     *
     * @param mapping Struts action mapping for this action
     * @param form Struts form bean for this action
     * @param request The Http Request
     * @param response The Http Response
     *
     * @return A struts action forward for where we will go next.
     * @throws Exception If there are any errors during processing.
     */
    public ActionForward displayReportData(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        
        CompletedReportsForm filterForm = (CompletedReportsForm)form;

        // Don't display the filter when we are refreshing the data in some way.
        filterForm.setDisplayFilter(false);

        // Set whether a filter was applied on the form
        filterForm.setFilterApplied(filterForm.getContainsFilterCriteria());

        // Get and store the value list information
        ValueList valueList =
            ValueListActionUtils.getValueList(form, request, getTableId(), getValueListAdapter());
        ValueListActionUtils.setValueList(request, valueList, "vlhlist");

        // Cache the report filters ONLY when filter cached flag set to true.  
        if (!filterForm.isFilterCached())
        {
            cacheReportFilters(request,filterForm);
        }

        // Process any info or error messages in session
        processMessagesInSession(request);

        // Display the reports
        return mapping.findForward(DISPLAY_DATA);
    }

    
    /**
     * Applies a report filter.
     * 
     * @param mapping Struts action mapping for this action
     * @param form Struts form bean for this action
     * @param request The Http Request
     * @param response The Http Response
     *
     * @return A struts action forward for where we will go next.
     * @throws Exception If there are any errors during processing.
     */
    public ActionForward applyFilter(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        
        CompletedReportsForm filterForm = (CompletedReportsForm)form;

        // Validate the filter and add error messages as needed.
        // Only refetch the data when we have valid filter information or if the data is already cached.
        if (!validateFilter(request, filterForm))
        {
            if (ValueListActionUtils.isCachedResults(request.getSession(), getTableId()))
            {
                // Re-wrap the valuelist results to make them accessible from the UI
                ValueList valueList = ValueListActionUtils
                    .getValueList(form, request, getTableId(), getValueListAdapter());
                ValueListActionUtils.setValueList(request, valueList, "vlhlist");
            }

            // Display the filter when there are validation errors.
            filterForm.setDisplayFilter(true);

            // Refresh the existing page without re-quering the data
            return mapping.findForward(DISPLAY_DATA);
        }
        else
        {
            // Refresh the data
            return refreshData(mapping, form, request, response);
        }
    }
    
    /**
     * This action entry point is different from
     * displayReportData in that it will clear the previously cached results first.
     * reset filterChached to false.
     *
     * @param mapping Struts action mapping for this action
     * @param form Struts form bean for this action
     * @param request The Http Request
     * @param response The Http Response
     *
     * @return A struts action forward for where we will go next.
     * @throws Exception If there are any errors during processing.
     */
    public ActionForward refreshData(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        CompletedReportsForm filterForm = (CompletedReportsForm)form;
        filterForm.setFilterCached(false);
        return super.refreshData(mapping, form, request, response);
    }
    
    /**
     * Deletes Completed Report.
     *
     * @param mapping Struts action mapping for this action
     * @param actionForm Struts form bean for this action
     * @param request The Http Request
     * @param response The Http Response
     *
     * @return A struts action forward for where we will go next.
     * @throws Exception If there are any errors during processing.
     */
    public ActionForward deleteCompletedReport(ActionMapping mapping, ActionForm actionForm,
        HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        // Get the report Id and create an entity key from it
        String reportId = request.getParameter(DELETE_REPORT_ID);
        String isInactiveReport = request.getParameter(IS_INACTIVE_REPORT);
        EntityKey key = CommonEntityKeyFactory.createSimpleCompletedReportEntityKey(reportId);

        try
        {
            // Deletes Completed Report
            getStandardReportService().deleteCompletedReport(key,this.getLoggedInUser());
        }
        catch (NoRecordFoundException ex)
        {
            // The report doesn't exist.  Perhaps it got deleted by another user.
            // Return to the completed reports list and display an error message.
            return mapping.findForward(DISPLAY_COMPLETED_REPORTS_DELETE_INVALID_ID);
        }
        // If it is an inactive report, Return to the completed reports and 
        // display archived report deletion successful message.
        if(isInactiveReport!=null && isInactiveReport.trim().equals("true"))
            return mapping.findForward(DISPLAY_COMPLETED_INACTIVE_REPORTS_DELETE_MSG);
        // Return to the completed reports list and display a success message.
        return mapping.findForward(DISPLAY_COMPLETED_REPORTS_DELETE_MSG);
    }
    
    /**
     * Deletes Completed Report.
     *
     * @param mapping Struts action mapping for this action
     * @param actionForm Struts form bean for this action
     * @param request The Http Request
     * @param response The Http Response
     *
     * @return A struts action forward for where we will go next.
     * @throws Exception If there are any errors during processing.
     */
    public ActionForward inactivateCompletedReport(ActionMapping mapping, ActionForm actionForm,
        HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        // Get the report Id and create an entity key from it
        String reportId = request.getParameter(INACTIVE_REPORT_ID);        
        EntityKey key = CommonEntityKeyFactory.createSimpleCompletedReportEntityKey(reportId);

        try
        {
            // Deletes Completed Report
            getStandardReportService().inactivateCompletedReport(key,this.getLoggedInUser());
        }
        catch (NoRecordFoundException ex)
        {
            // The report doesn't exist.  Perhaps it got deleted by another user.
            // Return to the completed reports list and display an error message.
            return mapping.findForward(DISPLAY_COMPLETED_REPORTS_INACTIVATE_INVALID_ID);
        }catch (ReportException rx)
        {
            // This report is inactive.  Perhaps it got inactivated by by another user.
            // Return to the completed reports list and display an error message.
            return mapping.findForward(DISPLAY_COMPLETED_REPORTS_INACTIVATION_INVALID);
        }
        
        // Return to the completed reports list and display a success message.
        return mapping.findForward(DISPLAY_COMPLETED_REPORTS_INACTIVATED_MSG);
    }
    
    /**
     * Validates the filter data and adds error messages as needed.
     *
     * @param request The HttpServletRequest.
     * @param form The completed reports form.
     *
     * @return True if the filters are valid or false if not.
     * @throws gov.va.med.esr.service.UnknownLookupCodeException if the lookup code for the Report Id is invalid (should
     * never happen).
     * @throws gov.va.med.esr.service.UnknownLookupTypeException if the lookup type for the Report Id is invalid (should
     * never happen).
     */
    protected boolean validateFilter(HttpServletRequest request, CompletedReportsForm form)
        throws UnknownLookupCodeException, UnknownLookupTypeException
    {
        // Assume filter is valid
        boolean valid = super.validateFilter(request, form);
         if (StringUtils.isNotEmpty(form.getInactivatedDate()))
        {
            try
            {
                // Validate inactivated date.
                Date archivedDate = DateUtils.getDate(form.getInactivatedDate());
            }
            catch (Exception e)
            {
                addActionMessageForField(request,
                    new ActionMessage(ApplicationConstants.MessageKeys.ERRORS_DATE, form.getInactivatedDate()),
                    LABEL_REPORT_ARCHIVED_DATE);
                valid = false;
            }
        }

        // Return whether the filter is valid or not
        return valid;
    }
    
    /**
     * Caches the report filters in session.
     *
     * @param reportList The list of reports.  This must be either a list of one of the following: SimpleCompletedReport
     * or ReportSetupLite.
     * @param request the HttpServletRequest.
     */
    protected void cacheReportFilters( HttpServletRequest request, CompletedReportsForm form)throws Exception
    {
       
        ReportFilter reportFilter=getStandardReportService().getCompletedReportFilter();
        
        List statusList=new ArrayList();
        // If active reports count is greater than 0, add Active option to report status.
        if(reportFilter.getActiveReportsCount() > 0 )
            statusList.add(getLookupCacheService().getByCodeFromCache(ReportStatus.class, ReportStatus.ACTIVE.getCode()));
        // If inactive reports count is greater than 0, add Inactive option to report status.
        if(reportFilter.getInactiveReportsCount() > 0 )
            statusList.add(getLookupCacheService().getByCodeFromCache(ReportStatus.class, ReportStatus.INACTIVE.getCode()));
        //Set Report status list in session to display it on completed reports screen.
        request.getSession().setAttribute(REPORT_STATUS_LIST, statusList);
        
        // Sort out the various filters in their own maps.
        // Putting them into maps will eliminate duplicates since the map key's are the displayable values.
        Map reportTypeMap = new HashMap();        
        
        if(reportFilter.getStandardReports()!=null)
        {
            for (Iterator iterator = reportFilter.getStandardReports().iterator(); iterator.hasNext();)
            {
                StandardReport standardReport = (StandardReport)iterator.next();
                if (standardReport != null)
                {                
                    // Process the report type
                    ReportType reportType = standardReport.getType();
                    if ((reportType != null) && (StringUtils.isNotEmpty(reportType.getDescription())) &&
                        (StringUtils.isNotEmpty(reportType.getCode())))
                    {
                        reportTypeMap.put(reportType.getCode(), reportType);
                    }
                }
            }        
            // Get report type list.
            List reportTypeList = new ArrayList(reportTypeMap.values());
            List reportIdList = new ArrayList(reportFilter.getStandardReports());
            List reportTitleList = new ArrayList(reportFilter.getStandardReports());
            List fileTypeList = reportFilter.getReportFileTypes();
            
            // Cache the report titles (Standard reports sorted by description)
            Collections.sort(reportTitleList, StandardReport.getNameComparator());
            request.getSession().setAttribute(REPORT_TITLE_LIST, reportTitleList);
    
            // Cache the report Ids (Standard reports sorted by code)
            Collections.sort(reportIdList, StandardReport.getCodeComparator());
            request.getSession().setAttribute(REPORT_ID_LIST, reportIdList);
    
            // Cache the report types (Report Type sorted by description)
            Collections.sort(reportTypeList, ReportType.getReportTypeNameComparator());
            request.getSession().setAttribute(REPORT_TYPE_LIST, reportTypeList);
    
            // Cache the file types (Report Exported Type sorted by description)
            Collections.sort(fileTypeList, ReportExportedType.getNameComparator());
            request.getSession().setAttribute(FILE_TYPE_LIST, fileTypeList);
        }
        form.setFilterCached(true);
    }
    
    /**
     * Reset CompletedReportsForm and filter cached to false.
     * Refresh the Data.
     */
    public ActionForward resetFilter(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) throws Exception
        {
            // Reset the filter values
            CompletedReportsForm filterForm = (CompletedReportsForm)form;
            filterForm.resetFilter();
            filterForm.setFilterCached(false);
            // Refresh the data
            return refreshData(mapping, form, request, response);
        }

}
