/*
 * Created on Feb 14, 2006
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package gov.va.med.esr.ui.taglib;


/**
 * @author DNS   CHENB
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;

import net.mlw.vlh.ValueListInfo;
import net.mlw.vlh.web.util.JspUtils;
import net.mlw.vlh.web.tag.*;
import net.mlw.vlh.web.tag.support.*;

import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;

import gov.va.med.fw.ui.valuelist.SelectableSearchValueListAdapter;
import gov.va.med.fw.service.pagination.SearchQueryInfo;

/**
 * Generate buttons to navigate through pages of data using i18n
 * (internationalization). The following keys are required to be define in
 * message sources.
 * 
 * <p>
 * If you like to, you can add your properties file in your locale and add this
 * lines of code in your language:
 * </p>
 * Summary info:
 * <ol>
 * <code>
 *     <li>paging.text.totalRow={0} Total  </li>
 *     <li>paging.text.pageFromTotal= <b>{0}</b> of  {1} page(s) </li>
 *  </code>
 * </ol>
 * Paging info:
 * <ol>
 * <li>paging.first(off), paging.first(on)</li>
 * <li>paging.previous(off), paging.previous(on)</li>
 * <li>paging.forward(off), paging.forward(on)</li>
 * <li>paging.last(off), paging.last(on)</li>
 * <li>paging.delim</li>
 * <li>paging.text.totalRow</li>
 * <li>paging.text.pageFromTotal</li>
 * </ol>
 * Focus info:
 * <ol>
 * <li>paging.focus(on), paging.focus(off), paging.focus(disabled),
 * paging.focus(error)</li>
 * </ol>
 * 
 * @todo Document this tag. AAA separate summary to differnt tag, find better
 *       pictures for paging.focus
 * @author Matthew L. Wilson, Andrej Zachar
 * @version $Revision: 1.25 $ $Date: 2005/03/16 13:14:11 $
 */
public class PagingSelectedTag extends ConfigurableTag
{
    private static final long serialVersionUID = -7960507634063427309L;
    
    public static final String SELECTED_REQUEST_ATTRIBUTE_KEY = SelectableSearchValueListAdapter.SELECTED_REQUEST_ATTRIBUTE_KEY;
    public static final String CHECKBOX_PARAM = 
    	gov.va.med.esr.ui.taglib.support.HtmlDisplayCheckBoxSortingProvider.CHECKBOX_PARAM;
    
    	
    private int pages = 0;

    private boolean showSummary = false;

    private int page;

    private int total;

    private int qtyOnPage;

    private int numberOfPages;

    private int currentPage = 0;

    private int maxPage = 0;

    private ValueListSpaceTag _parent;

    private Map parameters;

    /**
     * Creates new GridTag
     */
    public PagingSelectedTag()
    {
        super();        
    }



    /**
     * @see javax.servlet.jsp.tagext.TagSupport.doStartTag()
     */
    public int doStartTag() throws JspException
    {
        _parent = (ValueListSpaceTag) JspUtils.getParent(this,
                ValueListSpaceTag.class);

        Locale local = _parent.getConfig().getLocaleResolver().resolveLocale(
                (HttpServletRequest) pageContext.getRequest());
        MessageSource message = _parent.getConfig().getMessageSource();

        // Create a map of parameters that are used to generate the links.
        parameters = new HashMap(_parent.getTableInfo().getParameters());
        parameters.remove(SELECTED_REQUEST_ATTRIBUTE_KEY);
        if (parameters.get(CHECKBOX_PARAM) == null)
        	throw new JspException("Can not find param: checkboxName.\nPlease addParam under root. Example\n<vlh:addParam name=\"checkboxName\" value=\"selected\" temp=\"false\"/>");
        
		//parameters.put("callerKey", SearchQueryInfo.ACTION_PAGE);
		
        StringBuffer sb = new StringBuffer();

        page = _parent.getValueList().getValueListInfo().getPagingPage();
        total = _parent.getValueList().getValueListInfo()
                .getTotalNumberOfEntries();
        qtyOnPage = _parent.getValueList().getValueListInfo()
                .getPagingNumberPer();
        numberOfPages = _parent.getValueList().getValueListInfo()
                .getTotalNumberOfPages();

        currentPage = (int) (page - (pages / 2));
        if (currentPage < 1)
        {
            currentPage = 1;
        }

        maxPage = (currentPage - 1) + pages;
        if (maxPage > numberOfPages)
        {
            currentPage -= (maxPage - numberOfPages);
            maxPage = numberOfPages;
        }
        if (maxPage < 2)
        {
            maxPage = 0;
        }
        if (currentPage < 1)
        {
            currentPage = 1;
        }

        sb.append("\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"" 
                + (getAttributes()==null ? "":(" "+getAttributes()))
                + ">\n");
        sb.append("  <tr>\n");

        if (showSummary == true)
        {
            sb.append(generateSumary(message, local));
            sb.append("     <td align=\"right\">\n");
            sb
                    .append("\n      <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" >\n");
            sb.append("          <tr>\n");

        }

        String value = null;

        String delim = _parent.getConfig().getDisplayHelper().help(pageContext,
                message.getMessage("paging.delim", null, "", local));

        sb
                .append(generateFocusControl(_parent.getValueList()
                        .getValueListInfo(), delim, message, local));

        if (page > 1)
        {
            sb.append("   <td><a href=\"");
            sb.append(addScript(parameters.get(CHECKBOX_PARAM)));
            sb.append(_parent.getTableInfo().getUrl());
            parameters.put(ValueListInfo.PAGING_PAGE
                    + _parent.getTableInfo().getId(), "1");
            sb.append(_parent.getConfig().getLinkEncoder().encode(pageContext,
                    parameters));
            sb.append("\')\">");
            sb.append(
                    value = _parent.getConfig().getDisplayHelper()
                            .help(
                                    pageContext,
                                    message.getMessage("paging.first(on)",
                                            null, local)))
                    .append("</a></td>\n");
            if (value.length() > 0 && delim.length() > 0)
            {
                sb.append("   <td>").append(delim).append("</td>\n");
            }
            sb.append("   <td><a href=\"");
            sb.append(addScript(parameters.get(CHECKBOX_PARAM)));
            sb.append(_parent.getTableInfo().getUrl());
            parameters.put(ValueListInfo.PAGING_PAGE
                    + _parent.getTableInfo().getId(), String.valueOf(page - 1));
            sb.append(_parent.getConfig().getLinkEncoder().encode(pageContext,
                    parameters));
            sb.append("\')\">");
            sb.append(
                    value = _parent.getConfig().getDisplayHelper().help(
                            pageContext,
                            message.getMessage("paging.previous(on)", null,
                                    local))).append("</a></td>\n");
            if (value.length() > 0 && delim.length() > 0)
            {
                sb.append("   <td>").append(delim).append("</td>\n");
            }
        }
        else
        {
            sb.append("   <td>").append(
                    _parent.getConfig().getDisplayHelper().help(
                            pageContext,
                            message
                                    .getMessage("paging.first(off)", null,
                                            local))).append("</td>\n");
            sb.append("   <td>").append(
                    _parent.getConfig().getDisplayHelper().help(
                            pageContext,
                            message.getMessage("paging.previous(off)", null,
                                    local))).append("</td>\n");
        }

        JspUtils.write(pageContext, sb.toString());
        pageContext.setAttribute("page" + _parent.getTableInfo().getId(),
                new Integer(currentPage));

        return EVAL_BODY_AGAIN;
    }

    private String addScript(Object fieldName)
    {
        return gov.va.med.esr.ui.taglib.support.HtmlDisplayCheckBoxSortingProvider.addScript(fieldName);
    }
    /**
     * @param sb
     * @throws JspException
     * @throws NoSuchMessageException
     */
    private StringBuffer generateSumary(MessageSource message, Locale local)
            throws NoSuchMessageException, JspException
    {
        StringBuffer sb = new StringBuffer();

        sb.append(" <td nowrap=\"true\" valign=\"top\" align=\"left\">");
        sb.append(_parent.getConfig().getDisplayHelper().help(pageContext,
                message.getMessage("paging.text.totalRow", new Object[]
                { new Integer(total) }, local)));
        sb.append(_parent.getConfig().getDisplayHelper().help(pageContext,
                message.getMessage("paging.text.pageFromTotal", new Object[]
                { new Integer(page), new Integer(numberOfPages) }, local)));
        sb.append(" </td>\n");
        return sb;
    }

    /**
     * @param local
     * @param message
     * @param sb
     * @param delim
     * @throws JspException
     */
    private StringBuffer generateFocusControl(ValueListInfo info, String delim,
            MessageSource message, Locale local) throws JspException
    {
        String value;

        StringBuffer sb = new StringBuffer();

        if (info.isFocusEnabled() == true)
        {
            parameters.put(ValueListInfo.FOCUS_PROPERTY
                    + _parent.getTableInfo().getId(), info.getFocusProperty());

            if (info.getFocusValue() != null)
            {
                parameters.put(ValueListInfo.FOCUS_VALUE
                        + _parent.getTableInfo().getId(), info.getFocusValue());
            }
            // AAA focus error behavier
            HashMap focusParameters = new HashMap(parameters);
            if (info.getFocusStatus() != ValueListInfo.FOCUS_TOO_MANY_ITEMS)
            {
                sb.append("   <td><a href=\"");
                sb.append(addScript(parameters.get(CHECKBOX_PARAM)));
                sb.append(_parent.getTableInfo().getUrl());
                focusParameters.put(ValueListInfo.DO_FOCUS
                        + _parent.getTableInfo().getId(),
                        info.isDoFocusAgain() ? "false" : "true");

                sb.append(_parent.getConfig().getLinkEncoder().encode(
                        pageContext, focusParameters));
                sb.append("\')\">");
                sb
                        .append(
                                value = _parent
                                        .getConfig()
                                        .getDisplayHelper()
                                        .help(
                                                pageContext,
                                                message
                                                        .getMessage(
                                                                info
                                                                        .isDoFocusAgain() ? "paging.focus(off)"
                                                                        : "paging.focus(on)",
                                                                null, local)))
                        .append("</a></td>\n");
                if (value.length() > 0 && delim.length() > 0)
                {
                    sb.append("   <td>").append(delim).append("</td>\n");
                }
            }
            else
            {
                if (info.isFocusEnabled() == true)
                {
                    sb.append("   <td>").append(
                            _parent.getConfig().getDisplayHelper().help(
                                    pageContext,
                                    message.getMessage("paging.focus(error)",
                                            null, local))).append("</td>\n");
                }
            }

        }
        else
        {
            sb.append("   <td>").append(
                    _parent.getConfig().getDisplayHelper().help(
                            pageContext,
                            message.getMessage("paging.focus(disabled)", null,
                                    local))).append("</td>\n");
        }
        return sb;
    }

    /**
     * @see javax.servlet.jsp.tagext.IterationTag#doAfterBody()
     */
    public int doAfterBody() throws JspException
    {
        if (currentPage <= maxPage)
        {
            String label = getBodyContent().getString().trim();
            
            StringBuffer sb = getRenderedContent(label);
         
            JspUtils.writePrevious(pageContext, sb.toString());

            pageContext.setAttribute("page" + _parent.getTableInfo().getId(),
                    new Integer(++currentPage));
            getBodyContent().clearBody();
            return EVAL_BODY_AGAIN;
        }
        else
        {
            return SKIP_BODY;
        }
    }

    /**
     * @param label
     * @return
     */
    private StringBuffer getRenderedContent(String label) {
        StringBuffer sb = new StringBuffer();
        if (currentPage == page)
        {
            sb.append("<td>").append(label).append("</td>\n");
        }
        else
        {
            sb.append("<td><a href=\"");
            sb.append(addScript(parameters.get(CHECKBOX_PARAM)));
            sb.append(_parent.getTableInfo().getUrl());
            parameters.put(ValueListInfo.PAGING_PAGE
                    + _parent.getTableInfo().getId(), String
                    .valueOf(currentPage));
            sb.append(_parent.getConfig().getLinkEncoder().encode(
                    pageContext, parameters));
            sb.append("\')\">").append(label).append("</a></td>\n");
        }
        return sb;
    }

    /**
     * @see javax.servlet.jsp.tagext.TagSupport.doStartTag()
     */
    public int doEndTag() throws JspException
    {
        Locale local = _parent.getConfig().getLocaleResolver().resolveLocale(
                (HttpServletRequest) pageContext.getRequest());
        MessageSource message = _parent.getConfig().getMessageSource();

        StringBuffer sb = new StringBuffer();

        String value = null;
        String delim = _parent.getConfig().getDisplayHelper().help(pageContext,
                message.getMessage("paging.delim", null, local));

        if (!(getBodyContent() != null && getBodyContent().getString() != null && getBodyContent()
                .getString().trim().length() > 0))
        {
            while(currentPage <= maxPage)
            {
                sb.append(getRenderedContent(String.valueOf(currentPage)));
                currentPage++;
            }          
        }
        
        if (page < numberOfPages)
        {
            sb.append("   <td><a href=\"");
            sb.append(addScript(parameters.get(CHECKBOX_PARAM)));
            sb.append(_parent.getTableInfo().getUrl());
            parameters.put(ValueListInfo.PAGING_PAGE
                    + _parent.getTableInfo().getId(), String.valueOf(page + 1));
            sb.append(_parent.getConfig().getLinkEncoder().encode(pageContext,
                    parameters));
            sb.append("\')\">").append(
                    value = _parent.getConfig().getDisplayHelper().help(
                            pageContext,
                            message.getMessage("paging.forward(on)", null,
                                    local))).append("</a></td>\n");
            if (value.length() > 0 && delim.length() > 0)
            {
                sb.append("   <td>").append(delim).append("</td>\n");
            }
            sb.append("   <td><a href=\"");
            sb.append(addScript(parameters.get(CHECKBOX_PARAM)));
            sb.append(_parent.getTableInfo().getUrl());
            parameters.put(ValueListInfo.PAGING_PAGE
                    + _parent.getTableInfo().getId(), String
                    .valueOf(numberOfPages));
            sb.append(_parent.getConfig().getLinkEncoder().encode(pageContext,
                    parameters));
            sb.append("\')\">");
            sb.append(_parent.getConfig().getDisplayHelper().help(pageContext,
                    message.getMessage("paging.last(on)", null, local)));
            sb.append("</a></td>\n");
        }
        else
        {
            sb.append("   <td>").append(
                    _parent.getConfig().getDisplayHelper().help(
                            pageContext,
                            message.getMessage("paging.forward(off)", null,
                                    local))).append("</td>\n");
            sb.append("   <td>").append(
                    _parent.getConfig().getDisplayHelper()
                            .help(
                                    pageContext,
                                    message.getMessage("paging.last(off)",
                                            null, local))).append("</td>\n");
        }

        sb.append("  </tr>\n");
        sb.append("</table>\n");
        if (showSummary == true)
        {
            sb.append("     </td>\n");
            sb.append("</table>\n");
        }
        JspUtils.write(pageContext, sb.toString());

        pages = 0;
        showSummary = false;
        resetAttributes();
        
        return SKIP_BODY;
    }

    /**
     * @param pages The pages to set.
     */
    public void setPages(int pages)
    {
        this.pages = pages;
    }

    /**
     * @param showSummary The showSummary to set.
     */
    public void setShowSummary(String showSummary)
    {
        this.showSummary = ("true".equalsIgnoreCase(showSummary));
    }
}