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

// Java Classes
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

// Framework Classes
import gov.va.med.fw.service.ServiceConfigurationException;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.DateComparator;
import gov.va.med.fw.model.EntityKey;

// ESR Classes
import gov.va.med.esr.ui.common.action.AbstractAction;
import gov.va.med.esr.ui.ApplicationConstants;
import gov.va.med.esr.common.model.ee.EGTSetting;
import gov.va.med.esr.common.model.ee.EGTProcessStatistic;
import gov.va.med.esr.common.model.lookup.EnrollmentPriorityGroup;
import gov.va.med.esr.common.model.lookup.EnrollmentPrioritySubGroup;
import gov.va.med.esr.common.model.lookup.EGTSettingType;

import java.util.List;
import java.util.Set;
import java.util.Collections;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Date;
import java.sql.Timestamp;

/**
 * This is a struts action base class used for Add and Update EGT Settings pages.
 *
 * @author Andrew Pach
 * @version 3.0
 */
public class EGTSettingAction extends AbstractAction
{
    // Struts forwards
    public static final String FORWARD_EGT_SETTING_DISPLAY = "display";
    public static final String FORWARD_EGT_SETTING_OVERVIEW = "overview";
    public static final String FORWARD_EGT_SETTING_OVERVIEW_NO_REFRESH = "overviewNoRefresh";
    public static final String FORWARD_EGT_SETTING_OVERVIEW_WITH_STOP_MESSAGE = "overviewWithStopMessage";
    public static final String FORWARD_EGT_SETTING_OVERVIEW_WITH_NO_STOP_MESSAGE = "overviewWithNoStopMessage";
    public static final String FORWARD_EGT_SETTING_OVERVIEW_WITH_ADD_MESSAGE = "overviewWithAddMessage";
    public static final String FORWARD_EGT_SETTING_OVERVIEW_WITH_UPDATE_MESSAGE = "overviewWithUpdateMessage";
    public static final String FORWARD_EGT_SETTING_OVERVIEW_WITH_DISABLE_MESSAGE = "overviewWithDisableMessage";

    /**
     * Default constructor.
     */
    public EGTSettingAction()
    {
        super();
    }

    /**
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    public void afterPropertiesSet()
    {
    }

    /**
     * Checks to ensure the passed in ActionForm is not null and of the correct type.
     *
     * @param form The struts form to check
     *
     * @return The passed in form type-casted to our screen specific form
     * @throws gov.va.med.fw.service.ServiceConfigurationException if the form is null or of an incorrect type.
     */
    protected EGTSettingInfoForm getScreenSpecificForm(ActionForm form) throws ServiceConfigurationException
    {
        EGTSettingInfoForm specificForm = (form instanceof EGTSettingInfoForm) ? (EGTSettingInfoForm)form : null;
        if (specificForm == null)
        {
            throw new ServiceConfigurationException("EGTSettingInfoForm not properly configured.");
        }
        return specificForm;
    }

    /**
     * Sorts the EGT Settings by their effective date.  Null is returned if no settings exist.
     *
     * @param egtSettings The EGT Settings to sort.
     * @return The sorted list of EGT Settings.
     */
    protected List sortEGTSettings(Set egtSettings)
    {
        // Return null if no settings are present
        if (egtSettings == null)
        {
            return null;
        }

        List egtSettingsList = new ArrayList(egtSettings);
        Collections.sort(egtSettingsList, new BeanComparator("effectiveDate", new DateComparator()));
        return egtSettingsList;
    }

    /**
     * Cancels screen by going back to the overview page.
     *
     * @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 cancel(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        return mapping.findForward(FORWARD_EGT_SETTING_OVERVIEW_NO_REFRESH);
    }

    /**
     * Resets the data to its original state.
     *
     * @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 reset(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        // Convert the form to the specific one we need
        EGTSettingInfoForm egtForm = getScreenSpecificForm(form);

        // Get the EGT Setting ID
        String egtSettingId = egtForm.getEgtSettingId();

        // Reset the form
        egtForm.reset(mapping, request);

        // Place the ID back in the form
        egtForm.setEgtSettingId(egtSettingId);

        // Re-display the screen
        return display(mapping, form, request, response);
    }

    /**
     * Default display method which throws an exception.  This is needed by common methods in this
     * class (e.g. reset) which require the ability to go to a display screen when completed.  All
     * classes that use one of these common methods should implement a proper display method by
     * overwriting this method.
     *
     * @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 display(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        throw new Exception("Action called a method which required a display method that wasn't " +
            "implemented.");
    }

    /**
     * Refreshes all the EGT Settings in the session by reading new data from the service layer
     * and storing the results in session scope.
     * @param request The HttpServletRequest
     * @throws ServiceException if any problems were countered reading the new EGT Setting data.
     */
    protected void refreshEGTSettings(HttpServletRequest request) throws ServiceException
    {
        // Refresh the current EGT Setting
        setCurrentEGTSetting(request, getEgtService().getCurrentEGTSetting());

        // Refresh the future EGT Settings
        setFutureEGTSettings(request, sortEGTSettings(getEgtService().getFutureEGTSettings()));
    }

    /**
     * Gets an EGT Setting object that was previosly read into session state based on the
     * passed in entity key.  If no EGT Setting matches the passed in entity key, null is returned.
     * @param request The HttpServletRequest
     * @param entityKey The entity key for the EGT Setting to retrieve.
     * @return The EGT Setting that matches the passed in entity key or null if no match is found.
     */
    protected EGTSetting getEGTSettingByEntityKey(HttpServletRequest request, EntityKey entityKey)
    {
        // Try the current EGT Setting first
        EGTSetting egtSetting = getCurrentEGTSetting(request);
        if ((egtSetting != null) && (egtSetting.getEntityKey().equals(entityKey)))
        {
            // The passed in entity key matches the current EGT Setting
            return egtSetting;
        }

        // Try the future EGT Settings next
        List egtSettings = getFutureEGTSettings(request);
        if (egtSettings != null)
        {
            for (Iterator iterator = egtSettings.iterator(); iterator.hasNext();)
            {
                egtSetting = (EGTSetting)iterator.next();
                if (egtSetting.getEntityKey().equals(entityKey))
                {
                    // The passed in entity key matches one of the future EGT Settings
                    return egtSetting;
                }
            }
        }

        // No EGT Setting matches the passed in entity key so return null
        return null;
    }

    /**
     * Places the current EGT Setting into session scope
     * @param request The HttpServletRequest
     * @param egtSetting The current EGT Setting
     */
    protected void setCurrentEGTSetting(HttpServletRequest request, EGTSetting egtSetting)
    {
        putSandboxEntry(request, ApplicationConstants.SessionData.CURRENT_EGT_SETTING, egtSetting);
    }

    /**
     * Gets the current EGT Setting from session scope
     * @param request The HttpServletRequest
     * @return the current EGT Setting
     */
    protected EGTSetting getCurrentEGTSetting(HttpServletRequest request)
    {
        return (EGTSetting)getSandboxEntry(request, ApplicationConstants.SessionData.CURRENT_EGT_SETTING);
    }

    /**
     * Places the list of future EGT Settings in session scope
     * @param request The HttpServletRequest
     * @param egtSettings The list of EGT Settings
     */
    protected void setFutureEGTSettings(HttpServletRequest request, List egtSettings)
    {
        putSandboxEntry(request, ApplicationConstants.SessionData.FUTURE_EGT_SETTINGS, egtSettings);
    }

    /**
     * Gets the list of EGT Settings from session scope
     * @param request The HttpServletRequest
     * @return The list of EGT Settings
     */
    protected List getFutureEGTSettings(HttpServletRequest request)
    {
        return (List)getSandboxEntry(request, ApplicationConstants.SessionData.FUTURE_EGT_SETTINGS);
    }

    /**
     * Initialize and get the Struts lookup dispatch method map hashmap for common methods.
     *
     * @return the method map
     * @see org.apache.struts.actions.LookupDispatchAction#getKeyMethodMap()
     */
    protected Map getKeyMethodMap()
    {
        Map map = new HashMap();
        map.put("button.cancel", "cancel");
        map.put("button.reset", "reset");
        map.put("button.clear", "reset");
        return map;
    }
}