/********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.ui.report.action;

// Java imports

import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

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

// Libraries
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

// ESR imports
import gov.va.med.esr.common.model.registry.RegistryLoadStatistics;
import gov.va.med.esr.common.model.report.ReportSetup;
import gov.va.med.esr.common.model.security.ESRUserPrincipal;
import gov.va.med.esr.common.model.lookup.ReportFacilityDisplayBy;
import gov.va.med.esr.common.model.lookup.StandardReport;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.lookup.VISN;
import gov.va.med.esr.common.report.data.ParameterConfig;

import gov.va.med.fw.model.lookup.Lookup;
import gov.va.med.fw.security.UserPrincipal;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.fw.util.StringUtils;

/**
 * Handler for report edit actions.
 * 
 * @author Muddaiah Ranga
 * @version 1.0
 */
public class ReportEditAction extends ReportAction {
    
    public static final String INVALID_VISNS_FACILITIES = "errors.report.invalidStationNumbers";
    public static final String INVALID_VISNS = "errors.report.invalidVISNs";
    public static final String INVALID_FACILITIES = "errors.report.invalidFacilities";
    /**
     * Displays available report list.
     * 
     * @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 displayReportParameters(ActionMapping mapping, 
                                                 ActionForm actionForm,
                                                 HttpServletRequest request, 
                                                 HttpServletResponse response) throws Exception {
        ReportParamInfoForm form = (ReportParamInfoForm)actionForm;
        String reportId = request.getParameter(REPORT_ID);
        if(StringUtils.isNotEmpty(reportId)) {
            StandardReport stdReport = this.getStandardReport(request,reportId);
            form.setReportId(reportId);
            form.setReportName(stdReport.getCodeDescription());
        }
        
        setDefaults(form, request);
        
        return mapping.findForward(DISPLAY_REPORT_PARAMETERS);
    }
    
    /**
     * Displays report list for scheduling.
     * 
     * @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 displayReportSelection(ActionMapping mapping, 
                                                ActionForm actionForm,
                                                HttpServletRequest request, 
                                                HttpServletResponse response) throws Exception {
        
        request.setAttribute(STANDARD_REPORT_LIST,this.getStandardReports(request));
        return mapping.findForward(DISPLAY_REPORT_SELECTION);
    }
    
    /**
     * Displays add new report schedule.
     * 
     * @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 displayAddReportSchedule(ActionMapping mapping, 
                                                  ActionForm actionForm,
                                                  HttpServletRequest request, 
                                                  HttpServletResponse response) throws Exception {
        ReportScheduleInfoForm form = (ReportScheduleInfoForm)actionForm;
        ActionForward forward = mapping.findForward(DISPLAY_ADD_REPORT_SCHEDULE);
        String reportId = form.getReportId();
        if(StringUtils.isEmpty(reportId)) {
            forward = mapping.findForward(DISPLAY_REPORT_SELECTION);
        } else {
            StandardReport stdReport = this.getStandardReport(request,reportId);
            form.setReportId(reportId);
            form.setReportName(stdReport.getCodeDescription());
            
            //REEG_00005330:Scheduled report incorrectly has default mail group
            //if(StringUtils.isEmpty(form.getEmailReportTo())) {
            //    form.setEmailReportTo(this.getReportParameterConfig().getDefaultEmail());
            //}
        }
        return forward;
    }
    
    /**
     * Adds new report schedule.
     * 
     * @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 addReportSchedule(ActionMapping mapping, 
                                           ActionForm actionForm,
                                           HttpServletRequest request, 
                                           HttpServletResponse response) throws Exception {
        ReportScheduleInfoForm form = (ReportScheduleInfoForm)actionForm;
        String reportId = form.getReportId();
        StandardReport stdReport = (StringUtils.isNotEmpty(reportId)) ? this.getStandardReport(request,reportId) : null;
        if(stdReport != null) {
            UserPrincipal user = this.getLoggedInUser();
            ReportSetup reportSetup = new ReportSetup();
            reportSetup.setSetupUser((ESRUserPrincipal)user);
            reportSetup.setReport(this.getStandardReport(request,reportId));
            this.getConversionService().convert(form,reportSetup);
            this.getStandardReportService().scheduleReport(user,reportSetup);
        } else { 
            //Display some message
        }
        return mapping.findForward(DISPLAY_SCHEDULED_REPORTS_WITH_MSG);
    }

    /**
     * Cancel the action.
     * 
     * @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 cancel(ActionMapping mapping, 
                                ActionForm actionForm,
                                HttpServletRequest request, 
                                HttpServletResponse response) throws Exception {
        return mapping.findForward(CANCEL);
    }
    
    
    /**
     * Kicks off a 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 generateReport(ActionMapping mapping, 
                                        ActionForm actionForm,
                                        HttpServletRequest request, 
                                        HttpServletResponse response) throws Exception {
        ReportParamInfoForm form = (ReportParamInfoForm)actionForm;
        String reportId = request.getParameter(REPORT_ID);
        StandardReport stdReport = (StringUtils.isNotEmpty(reportId)) ? this.getStandardReport(request,reportId) : null;
        if(stdReport != null) {
            UserPrincipal user = this.getLoggedInUser();
            ReportSetup reportSetup = new ReportSetup();
            reportSetup.setReport(stdReport);
            reportSetup.setSetupUser((ESRUserPrincipal)user);
            if (!isSitesListValid(form, request)){
                return mapping.getInputForward();
            }
            this.getConversionService().convert(form,reportSetup);
            this.getStandardReportService().generateReport(user,reportSetup);
        } else {
            //Display some message
        }
        return mapping.findForward(DISPLAY_AVAILABLE_REPORTS_WITH_MSG);
    }
    /**
     * Validate the list of sites/visns enetered by the user in free form text 
     * @param form
     * @param request
     * @return
     */
    private boolean isSitesListValid(ReportParamInfoForm form, HttpServletRequest request){
        String[] stationNumbers = form.getStationNumbersAsArray();
        boolean valid = true;
        boolean visns = false;
        boolean sites = false;
        StringBuffer invalidCodes = new StringBuffer();
        if ( stationNumbers != null && stationNumbers.length > 0){
            //validate each VISN or Site number entered
            for (int i=0; i<stationNumbers.length; i++) {
                String code = stationNumbers[i];
                Lookup lookupObj = null;
                try {
                    if (code.startsWith(VISN)){
                        visns = true;  //visns                      
                        lookupObj = getLookupCacheService().getByCodeFromCache(VISN.class,code);
                    }else {
                        sites = true; //vamcs and facilities
                        lookupObj = getLookupCacheService().getByCodeFromCache(VAFacility.class,code);
                    }                                        
                }catch (Exception e){
                    valid = false;
                }
                if (lookupObj == null){
                    valid = false;
                    invalidCodes.append(i==0 ? code : "," + code);
                }
            }            
        }
        if (!valid){
            //Add error message and return
            addActionMessageForField(request,INVALID_VISNS_FACILITIES,
                invalidCodes.toString(),"stattionNumbers");
        }
        if (valid){
            //check for site and visn combinations based on user selections
            String facilityDisplayBy = form.getFacilityDisplayByNoDefault();
            //if the list contains non visn return with error message            
            if(sites && StringUtils.equals(facilityDisplayBy,ReportFacilityDisplayBy.CODE_VISN.getCode())) {
                addActionMessageForField(request,INVALID_VISNS, form.getStationNumbers(),"stattionNumbers");
                valid = false;
            }else if (visns && (
                    StringUtils.equals(facilityDisplayBy,ReportFacilityDisplayBy.CODE_SITE.getCode())
                    || StringUtils.equals(facilityDisplayBy,ReportFacilityDisplayBy.CODE_VAMC.getCode())
                    || StringUtils.equals(facilityDisplayBy,ReportFacilityDisplayBy.CODE_VAMC_SITE.getCode()))){
                addActionMessageForField(request,INVALID_FACILITIES, form.getStationNumbers(),"stattionNumbers");
                valid = false;                
            }                                             
        }
        return valid;
    }
    
    
    private void setDefaults(ReportParamInfoForm form, HttpServletRequest request) throws Exception {
        ServletContext context = request.getSession().getServletContext();
        Map parameterMap = (Map)context.getAttribute(REPORT_PARAMETER_CONFIG);
        if (parameterMap == null) 
            return;
        String reportId = form.getReportIdNoSpace();
        Map reportParamMap = (Map)parameterMap.get(reportId);
        if (reportParamMap == null)
            return;
        
        PropertyUtilsBean propertyUtils = new PropertyUtilsBean();
        
        //Process configuration based defaults 
        //if default value is specified for any of the fields set the value
        for(Iterator iter = reportParamMap.keySet().iterator(); iter.hasNext();) {
            String fieldName = (String)iter.next();
            ParameterConfig paramConfig = (ParameterConfig)reportParamMap.get(fieldName);
            
            //Get the field configuration
            if(paramConfig != null) {
                String defaultValue = paramConfig.getDefaultValue();
                if (defaultValue != null){
                    if (ReportConstants.ALL.equals(defaultValue)){
                        String[] list = getAllLookupDefaults(fieldName);
                        if (list == null) {
                            list = new String[1];
                            list[0] = ReportConstants.ALL;
                        }
                        propertyUtils.setNestedProperty(form,fieldName,list);
                    }else{
                        propertyUtils.setNestedProperty(form,fieldName,defaultValue);
                    }
                }
            }
        }
        
        //Process report specific defaults
        if (reportId.equals("IV1")) {
            //set income year to current year
            String curYear = String.valueOf(DateUtils.getCurrentYear());
            form.setBeginIncomeYear(curYear);
            form.setEndIncomeYear(curYear);            
            //default facility selection to visn and all visns
            form.setFacilityDisplayBy(ReportFacilityDisplayBy.CODE_VISN.getCode());
            String[] allvisns = {ALL};
            form.setVisn(allvisns);
        }else if (reportId.equals("IV5")) {
            form.setFacilityDisplayBy(ReportFacilityDisplayBy.CODE_SITE.getCode());
            String[] allSites = {ALL};
            form.setFacility(allSites);
        }else if (reportId.equals("EED10")) {
            //default facility selection to visn and all visns
            form.setFacilityDisplayBy(ReportFacilityDisplayBy.CODE_VISN.getCode());
            String[] allvisns = {ALL};
            form.setVisn(allvisns);
        }else if (reportId.equals("QM10")) {
            //Cuurent fiscal year for the detailed report
            String fiscalYear = String.valueOf(gov.va.med.fw.util.DateUtils.getFiscalYear(Calendar.getInstance()));
            form.setReportPeriodYear(fiscalYear);
            form.setReportPeriodQuarterYear(fiscalYear);
        }else if (reportId.equals("QM27")) {
            //get the most recent processing batch number
            RegistryLoadStatistics stats = getRegistryService().getMostRecentRegistrySummaryByType(null);
            if (stats != null){
                form.setBatchNumber(stats.getEntityKey().getKeyValueAsString());
            }
        }
    }
    
    private String[] getAllLookupDefaults(String fieldName) throws Exception{
        Collection set = null;        
        if (REPORT_PARAM_REGISTRY_TYPE.equals(fieldName)){  //QM26
            set = getLookupCacheService().getFromCache(gov.va.med.esr.common.model.lookup.RegistryType.class.getName());
        }
        else if (REPORT_PARAM_LETTER_FILE.equals(fieldName)){ //COR1
            set = getLookupCacheService().getFromCache(gov.va.med.esr.common.model.lookup.ReportLetterFile.class.getName());
        }
        else if (REPORT_PARAM_CANCELLED_DECLINED_REASON.equals(fieldName)){ //QM4
            return null; //use default as it uses radio buttons
            //set = getLookupCacheService().getFromCache(gov.va.med.esr.common.model.lookup.CancelDeclineReason.class.getName());
        }
        else if (REPORT_PARAM_BAD_ADDRESS_REASON.equals(fieldName)){ //QM5
            set = getLookupCacheService().getFromCache(gov.va.med.esr.common.model.lookup.BadAddressReason.class.getName());
        }        
        else if (REPORT_PARAM_PH_REJECT_REASON.equals(fieldName)){ //QM23
            set = getLookupCacheService().getFromCache(gov.va.med.esr.common.model.lookup.RejectionRemark.class.getName());
        }

        if (set != null && set.size() > 0){
                String[] selectedValues = new String[set.size() + 1];
                int index = 0;
                selectedValues[index++]= ReportConstants.ALL;
                for (Iterator i=set.iterator(); i.hasNext();) {
                    Lookup lookup = (Lookup)i.next();
                    selectedValues[index++]= lookup.getCode();
                }
                return selectedValues;
        }
        return null;
    }        
}
