/*********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.fw.ui.struts;

// Java Classes
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

// Library Classes
import org.apache.struts.action.ActionForm;
import org.springframework.web.context.WebApplicationContext;
import net.mlw.vlh.ValueList;
import net.mlw.vlh.ValueListInfo;
import net.mlw.vlh.web.mvc.ValueListHandlerHelper;

// Framework Classes
import gov.va.med.fw.ui.DelegatingActionUtils;
import gov.va.med.fw.ui.valuelist.ValueListException;
import gov.va.med.fw.ui.valuelist.SearchValueListAdapter;
import gov.va.med.fw.ui.valuelist.SelectableResult;
import gov.va.med.fw.service.pagination.SearchQueryInfo;

/**
 * This class provides helper methods to aid with the ValueList package usage within Struts
 * Actions.
 *
 * @author Andrew Pach
 * @version 3.0
 */
public class ValueListActionUtils
{
    /**
     * This class is not meant to be instantiated.
     */
    private ValueListActionUtils()
    {
    }

    /**
     * Gets the value list by executing a search based on a ValueListAdapter.
     *
     * @param form The struts ActionForm that contains all the search criteria.
     * @param request The HttpServletRequest
     * @param tableId The table Id which will be used to retrieve any previously cached
     * ValueListInfo object.
     * @param valueListAdapterName The ValueListAdapter bean to use for performing the search.
     *
     * @return The value list
     * @throws ValueListException If any errors occur.
     */
    public static ValueList getValueList(ActionForm form, HttpServletRequest request,
        String tableId,
        String valueListAdapterName) throws ValueListException
    {
        return getValueList(form, request, tableId, valueListAdapterName, null);
    }

    /**
     * Gets the value list by executing a search based on a ValueListAdapter.
     *
     * @param form The struts ActionForm that contains all the search criteria.
     * @param request The HttpServletRequest
     * @param tableId The table Id which will be used to retrieve any previously cached
     * ValueListInfo object.
     * @param valueListAdapterName The ValueListAdapter bean to use for performing the search.
     * @param results An optional result list if the results are already known and a search is not
     * needed.
     *
     * @return The value list
     * @throws ValueListException If any errors occur.
     */
    public static ValueList getValueList(ActionForm form, HttpServletRequest request,
        String tableId,
        String valueListAdapterName, List results) throws ValueListException
    {
        // Get the ValueListHelper bean
        ValueListHandlerHelper valueListHelper = getValueListHandlerHelper(request);

        // Get the ValueListInfo from the session if previously saved using the tableId as a key, or create a new one.
        ValueListInfo valueListInfo = valueListHelper.getValueListInfo(request, tableId);

        // Get the filter map from ValueListInfo and store the form and HttpRequest so it will be passed to
        // the adapter
        Map filterMap = valueListInfo.getFilters();
        filterMap.put(SearchValueListAdapter.FORM_KEY, form);
        filterMap.put(SearchValueListAdapter.HTTP_REQUEST_KEY, request);
        filterMap.put(SearchValueListAdapter.TABLE_ID_KEY, tableId);
        filterMap.put(SearchValueListAdapter.RESULTS_KEY, results);

        // Get and return the value list results by specifying the adapter name and the valueListInfo.
        // This will ultimately look up the ValueListAdapter injected into ValueListHandler.
        return valueListHelper.getValueList(valueListAdapterName, valueListInfo);
    }

    /**
     * Updates the latest selectable results based on the latest user selections and returns a
     * ValueList which contains the list of SelectableResult objects.
     * <p/>
     * Note that this method should only be used when the SelectableSearchValueListAdapter is being
     * used.
     *
     * @param form The struts ActionForm that contains all the search criteria.
     * @param request The HttpServletRequest
     * @param tableId The table Id which will be used to retrieve any previously cached
     * ValueListInfo object.
     * @param valueListAdapterName The ValueListAdapter bean to use for performing the search.
     * @param results An optional result list if the results are already known and a search is not
     * needed.
     *
     * @return The value list
     * @throws ValueListException If any errors occur.
     */
    public static ValueList getSelectableResultValuleList(ActionForm form,
        HttpServletRequest request, String tableId,
        String valueListAdapterName, List results) throws ValueListException
    {
        SearchValueListAdapter.setAction(request, SearchQueryInfo.ACTION_SELECT);

        // Perform the normal value list processing to update the currently selected items
        // and return the SelectableResult objects.
        return getValueList(form, request, tableId, valueListAdapterName, results);
    }

    /**
     * Clears any previously cached results from a previous search.
     *
     * @param session The HttpSession
     * @param tableId The table Id for the valueList.
     */
    public static void clearCachedResults(HttpSession session, String tableId)
    {
        SearchValueListAdapter.setResultsInSession(session,
            tableId + SearchValueListAdapter.RESULTS_KEY, null);
        SearchValueListAdapter.setPrevPageInSession(session,
            tableId + SearchValueListAdapter.PREV_PAGE_KEY, null);
    }

    /**
     * Determines if any results are currently cached.
     *
     * @param session The HttpSession
     * @param tableId The table Id for the valueList.
     * @return true if any results are cached or false if not.
     */
    public static boolean isCachedResults(HttpSession session, String tableId)
    {
        return SearchValueListAdapter.getResultsFromSession(
            session, tableId + SearchValueListAdapter.RESULTS_KEY) != null;
    }

    /**
     * Returns any previously cached results.  If no results are cached, null is returned.
     *
     * @param session The HttpSession
     * @param tableId The table Id for the valueList.
     * @return The previously cached results.
     */
    public static List getCachedResults(HttpSession session, String tableId)
    {
        return SearchValueListAdapter.getResultsFromSession(session, tableId + SearchValueListAdapter.RESULTS_KEY);
    }

    /**
     * Returns a list of SelectableResult objects that match the selected criteria parameter.
     * <p/>
     * Note that this method should only be used when the SelectableSearchValueListAdapter is being
     * used.
     *
     * @param valueList the valueList that contains all the results SelectableResults.
     * @param selected Boolean that determines what filtering will be done on the returned list.
     * True will return only the selected values.  False will return only the unselected values.
     * Null will return all values.
     *
     * @return The filtered results.
     */
    public static List getSelectableResults(ValueList valueList, Boolean selected)
    {
        return getSelectableResults(valueList.getList(), selected);
    }

    /**
     * Returns a sub list of SelectableResult objects that match the selected criteria parameter on current page.
     * <p/>
     * Note that this method should only be used when the SelectableSearchValueListAdapter is being
     * used.
     *
     * @param results A list of SelectableResult objects.
     * @param selected Boolean that determines what filtering will be done on the returned list.
     * True will return only the selected values.  False will return only the unselected values.
     * Null will return all values.
     *
     * @return The filtered results.
     */
    public static List getSelectableResults(List results, Boolean selected)
    {
        // Filter out the appropriate records if the selected flag was passed in
        if (selected != null)
        {
            List updatedList = new ArrayList();
            for (Iterator iterator = results.iterator(); iterator.hasNext();)
            {
                SelectableResult selectableResult = (SelectableResult)iterator.next();
                if (selectableResult.isSelected() == selected.booleanValue())
                {
                    updatedList.add(selectableResult);
                }
            }

            // Update the selectable results
            results = updatedList;
        }

        // Return the filtered list
        return results;
    }
    
    /**
     * Returns a list of SelectableResult objects that match the selected criteria parameter.
     * <p/>
     * Note that this method should only be used when the SelectableSearchValueListAdapter is being
     * used.
     *
     * @param request The HttpServletRequest
     * @param tableId The table Id which will be used to retrieve whole list from session
     * @param selected Boolean that determines what filtering will be done on the returned list.
     * True will return only the selected values.  False will return only the unselected values.
     * Null will return all values.
     *
     * @return The filtered results.
     */
    public static List getSelectableResultsFromSession(
    		HttpServletRequest request,
			String tableId,
			Boolean selected)
    {
        List wholeResults = SearchValueListAdapter.getResultsFromSession(request.getSession(), tableId + SearchValueListAdapter.RESULTS_KEY);
        return getSelectableResults(wholeResults, selected);
    }
    
    
    
    
    public static List getSelectedResultsFromPreviousPage(
            HttpServletRequest request,
            String tableId,
            Boolean selected)
    {
        List prevPageResults = SearchValueListAdapter.getResultsFromSession(request.getSession(), tableId + SearchValueListAdapter.PREV_PAGE_RESULTS_KEY);
                     
        return getSelectableResults(prevPageResults, selected);
    }
    
    /**
     * Sets the ValueList into request scope under the specified key so it can be display on the
     * GUI.
     *
     * @param request The HttpServletRequest
     * @param valueList The ValueList to place on request scope.
     * @param requestKey The request key that will be used to store the ValueList.
     */
    public static void setValueList(HttpServletRequest request, ValueList valueList,
        String requestKey)
    {
        // Place valueList on the request using key requestKey.
        getValueListHandlerHelper(request).setValueListTo(request, valueList, requestKey);
    }

    /**
     * Returns the ValueListHandlerHelper bean.
     *
     * @param request The HttpServletRequest
     *
     * @return The ValueListHandlerHelper bean.
     */
    public static ValueListHandlerHelper getValueListHandlerHelper(HttpServletRequest request)
    {
        // Return the ValueListHandlerHelper bean
        return (ValueListHandlerHelper)getApplicationContext(request)
            .getBean(ValueListHandlerHelper.class.getName(),
                ValueListHandlerHelper.class);
    }

    /**
     * Returns the Spring web application context.
     *
     * @param request The HttpServletRequest
     *
     * @return The web application context
     */
    public static WebApplicationContext getApplicationContext(HttpServletRequest request)
    {
   	 return 	DelegatingActionUtils.findRequiredWebApplicationContext( request.getSession().getServletContext() );
    }
}