/*
 * @(#)RowsetNavigateTag.java
 *
 * Copyright 2001-2002 by Oracle Corporation,
 * 500 Oracle Parkway, Redwood Shores, California, 94065, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Oracle Corporation.
 */

package oracle.jbo.html.jsp.datatags;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
import oracle.jbo.JboException;
import oracle.jbo.RowSet;
import oracle.jbo.RowIterator;
import oracle.jbo.html.DataSource;
import oracle.jbo.html.HtmlServices;

public class RowsetNavigateTag extends TagSupport
{
   public static final String ACTION_NAV_FIRST         = "first";
   public static final String ACTION_NAV_FIRSTSET      = "firstSet";
   public static final String ACTION_NAV_PREVIOUS      = "previous";
   public static final String ACTION_NAV_PREVIOUSSET   = "previousSet";
   public static final String ACTION_NAV_NEXT          = "next";
   public static final String ACTION_NAV_NEXTSET       = "nextSet";
   public static final String ACTION_NAV_LAST          = "last";
   public static final String ACTION_NAV_LASTSET       = "lastSet";
   public static final String ACTION_NAV_GOTOSET       = "gotoSet";
   String sDataSource;
   String sAction;

   /**
    * Constructor
    */
   public RowsetNavigateTag()
   {
   }

   public void setDatasource(String sname)
   {
      this.sDataSource = sname;
   }

   public void setAction(String sAction)
   {
      this.sAction = sAction;
   }

   /**
     * Process the start tag for this instance.
     *
     * The doStartTag() method assumes that all setter methods have been
     * invoked before.
     *
     * When this method is invoked, the body has not yet been invoked.
     *
     * @returns EVAL_BODY_INCLUDE if the tag wants to process body, SKIP_BODY if it
     * does ont want to process it.
     */
   public int doStartTag() throws JspException
   {
      DataSource ds = Utils.getDataSourceFromContext(pageContext, sDataSource);
      RowSet rs = ds.getRowSet();

      // If the action is not set, try to get the action from the context
      if (sAction == null)
      {
         Tag tag = this.getParent();

         if(!(tag instanceof OnEventTag))
         {
            throw new JboException(Res.getString(Res.INVALID_NAVIGATE_ACTION));
         }

         sAction = ((OnEventTag) tag).getAction();
      }

      if (ACTION_NAV_NEXT.equalsIgnoreCase(sAction))
      {
         rs.next();
      }
      else if (ACTION_NAV_PREVIOUS.equalsIgnoreCase(sAction))
      {
         rs.previous();
      }
      else if (ACTION_NAV_FIRST.equalsIgnoreCase(sAction))
      {
         rs.first();
      }
      else if (ACTION_NAV_LAST.equalsIgnoreCase(sAction))
      {
         rs.last();
      }
      else if (ACTION_NAV_FIRSTSET.equalsIgnoreCase(sAction))
      {
         rs.setRangeStart(0);
      }
      else if (ACTION_NAV_NEXTSET.equalsIgnoreCase(sAction))
      {
         rs.scrollRange(rs.getRangeSize());
      }
      else if (ACTION_NAV_PREVIOUSSET.equalsIgnoreCase(sAction))
      {
         int scrollAmount;
         int rangeSize = rs.getRangeSize();
         
         if (rs.getIterMode() == RowIterator.ITER_MODE_LAST_PAGE_FULL)
         {
            long totalCount = rs.getEstimatedRowCount();
            long rangeStart = rs.getRangeStart();
            
            // If at the end of the set, only go back to the previous zero base step
            if (rangeStart + rangeSize == totalCount)
            {
               scrollAmount = (int) (((rangeStart / rangeSize) * rangeSize) - rangeStart);
            }
            else
            {
               scrollAmount = -rangeSize;
            }
         }
         else
         {
            scrollAmount = -rangeSize;
         }
         
         rs.scrollRange(scrollAmount);
      }
      else if (ACTION_NAV_LASTSET.equalsIgnoreCase(sAction))
      {
         int rangeSize = rs.getRangeSize();

         while (rs.scrollRange(rangeSize) > 0);
      }
      else if (ACTION_NAV_GOTOSET.equalsIgnoreCase(sAction))
      {
         String value = HtmlServices.getRequestParameter(pageContext, "value");
         int start = -1;
         if (value != null)
         {
            try
            {
               start = Integer.parseInt(value) - 1;
            }
            catch (NumberFormatException ex)
            {
            }
   
            if (start >= 0)
            {
               rs.setRangeStart(start);
            }
         }
      }
      else
      {
         throw new JboException(Res.getString(Res.INVALID_NAVIGATE_ACTION));
      }
      
      return Tag.SKIP_BODY;
   }

   /**
   * release() called after doEndTag() to reset state
   */
   public void release()
   {
      sDataSource = null;
      sAction = null;

      super.release();
   }
}
