/*
 * @(#)InputTagBase.java
 *
 * Copyright 2000-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 java.lang.reflect.Method;

import com.sun.java.util.collections.HashMap;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.PageContext;
import oracle.jbo.Row;
import oracle.jbo.JboException;
import oracle.jbo.common.JBOClass;
import oracle.jbo.html.HtmlServices;
import oracle.jdeveloper.html.HTMLFieldRenderer;
import oracle.jdeveloper.html.TextField;

abstract public class InputTagBase extends DataTagBase
{
   protected String            sReadonly;
   protected HTMLFieldRenderer rndObj;
   protected int               nCols;
   protected int               nMaxLength;
   protected HashMap           htmlAttrs;

   public InputTagBase()
   {
      super();
      reset();
   }

   public void setCols(String sValue)
      throws java.lang.NumberFormatException
   {
      nCols = Integer.parseInt(sValue);
   }

   public void setMaxlength(String sValue)
      throws java.lang.NumberFormatException
   {
      nMaxLength = Integer.parseInt(sValue);
   }

   public void setReadonly(String sValue)
   {
      sReadonly = sValue;
   }

   public void addHtmlAttribute(String name, String value)
   {
      if (htmlAttrs == null)
      {
         htmlAttrs = new HashMap();
      }

      htmlAttrs.put(name, value);
   }

   abstract public HTMLFieldRenderer getFieldRenderer();

   protected void initializeRow()
   {
      // Retrieve the row from the first RowsetIterate tag or Row tag matching our datasource name
      row = Utils.getRowFromAncestor(this, sDataSource);
      if (row == null)
      {
         // In the Struts case with a Struts Form tag, we get the row from the tag.
         if (HtmlServices.isStrutsContext(pageContext) &&  getStrutsFormTag() != null)
         {
            try
            {
               // Use BEAN_KEY = org.apache.struts.taglib.html.BEAN
               Object formBean = pageContext.getAttribute("org.apache.struts.taglib.html.BEAN", PageContext.REQUEST_SCOPE);
               if (formBean != null)
               {
                  Class cls = JBOClass.forName("oracle.jbo.html.struts11.BC4JActionForm");
                  Method getRow = cls.getMethod("getRow", null);
                  row = (Row) getRow.invoke(formBean, null);
               }
            }
            catch (java.lang.ClassNotFoundException ex)
            {
               throw new JboException(ex.getMessage());
            }
            catch (java.lang.NoSuchMethodException ex)
            {
               throw new JboException(ex.getMessage());
            }
            catch (java.lang.reflect.InvocationTargetException ex)
            {
               throw new JboException(ex.getMessage());
            }
            catch (java.lang.IllegalAccessException ex)
            {
               throw new JboException(ex.getMessage());
            }

            return;
         }
      }
      
      // If Row tag failed too, use the current row
      if (row == null && ds != null)
      {
         row = ds.getRowSet().getCurrentRow();
         if (row == null)
         {
            row = ds.getRowSet().first();
         }
      }

      // Last resort throws
      if (row == null)
      {
         throw new JboException(Res.format(Res.INPUTTAG_NO_ROWS, sDataSource));
      }
   }
   
   protected void initializeFieldRenderer(HTMLFieldRenderer rField)
   {
      rField.setDatasource(ds);
      rField.setAttributeDef(attrDef);

      rField.setValue(null);
      rField.setPageContext(pageContext);
   }
   
   protected void initializeAttributeDef()
   {
      // Special handling of ROWKEY as the dataitem
      if (!ShowValueTag.UI_ROWKEY.equalsIgnoreCase(sDataItem))
      {
         super.initializeAttributeDef();
      
         if (attrDef == null)
         {
            throw new JboException(Res.getString(Res.INPUTTAG_NO_DATAITEM));
         }

         // get the renderer for the attribute type
         rndObj = getFieldRenderer();
      }
      else
      {
         // get the renderer for the attribute type
         rndObj = getFieldRenderer();
      
         if (row != null)
         {
            rndObj.setValue(row.getKey().toStringFormat(true));
         }

         sReadonly = "true";

         rndObj.setFieldName(ShowValueTag.UI_ROWKEY);
      }
   }

   public void internalInitialize()
   {
      super.internalInitialize();
      
      if (nCols >= 0)
      {
         rndObj.setDisplayWidth(nCols);
      }

      if (nMaxLength >= 0)
      {
         rndObj.setMaxDataLength(nMaxLength);
      }

      if (sReadonly != null)
      {
         if (rndObj instanceof TextField)
         {
            ((TextField) rndObj).setReadOnly(Utils.isTrue(sReadonly));
         }
      }
   }

   protected Tag getStrutsFormTag()
   {
      // Look for a Struts Form tag to get the form name out of it.
      try
      {
         Class cls = JBOClass.forName("org.apache.struts.taglib.html.FormTag");
         return findAncestorWithClass(this, cls);
      }
      catch (java.lang.ClassNotFoundException ex)
      {
         throw new JboException(ex.getMessage());
      }
   }
   
   protected String getStrutsFormName()
   {
      // Look for a Struts Form tag to get the form name out of it.
      try
      {
         Class cls = JBOClass.forName("org.apache.struts.taglib.html.FormTag");
      
         Tag formTag = findAncestorWithClass(this, cls);
         if (formTag == null)
         {
            throw new JboException(Res.getString(Res.INPUTDATE_MISSING_FORMTAG));
         }

        Method getName = cls.getMethod("getName", null);
        return (String) getName.invoke(formTag, null);
      }
      catch (java.lang.ClassNotFoundException ex)
      {
         throw new JboException(ex.getMessage());
      }
      catch (java.lang.NoSuchMethodException ex)
      {
         throw new JboException(ex.getMessage());
      }
      catch (java.lang.reflect.InvocationTargetException ex)
      {
         throw new JboException(ex.getMessage());
      }
      catch (java.lang.IllegalAccessException ex)
      {
         throw new JboException(ex.getMessage());
      }
   }


   /**
     * 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
   {
      internalInitialize();
      
      return Tag.EVAL_BODY_INCLUDE;
   }
   
   public int doEndTag() throws JspException
   {
      if (htmlAttrs != null && !htmlAttrs.isEmpty())
      {
         rndObj.setHtmlAttributes(htmlAttrs);
      }
         
      try
      {
         String content;

         if (HtmlServices.isStrutsContext(pageContext) && getStrutsFormTag() != null)
         {
            content = rndObj.renderToString(null);
         }
         else
         {
            content = rndObj.renderToString(row);
         }
         pageContext.getOut().print(content);
      }
      catch (java.io.IOException ex)
      {
         pageContext.getServletContext().log(Res.getString(Res.IO_ERROR), ex);
         throw new JspTagException(ex.getMessage());
      }
      
      return super.doEndTag();
   }
   
   // Use by the constructor and the release method to reset the member variable values
   private void reset()
   {
      rndObj = null;
      nCols = -1;
      nMaxLength = -1;
      sReadonly = null;
      if (htmlAttrs != null)
      {
         htmlAttrs.clear();
      }
   }
   
   /**
     * release() called after doEndTag() to reset state
     */
   public void release()
   {
      reset();
      super.release();
   }

}
