/********************************************************************
 *  Oracle JDeveloper
 *  Copyright (c) 1997, 1999, Oracle Corporation. All rights reserved.
 ********************************************************************/

package oracle.jdeveloper.html;

import oracle.jdeveloper.html.*;
import oracle.jbo.*;
import java.util.*;

/**
 * This class represents a databound picklist. It binds to data from a BC4J view object. It supports various renderings:
 * combobox, listbox,radio group and checbox group.
 *
 * @author  Juan Oropeza
 * @version PUBLIC
 *
 **/
public class PickList extends HTMLFieldRendererImpl
{
  public static final int TYPE_COMBOBOX = 0;
  public static final int TYPE_LISTBOX = 1;
  public static final int TYPE_CHECKBOX_GROUP = 2;
  public static final int TYPE_RADIO_GROUP = 3;

  protected   int    nType = TYPE_COMBOBOX;
  protected   boolean bAddNullEntry    = false;
  

  protected   String    sQuery = "";
  protected   HTMLForm  aForm = null;
  protected   RowSet    qView;
  protected   String    labelAttr;
  protected   String    dataAttr;
  protected   Hashtable values = new Hashtable();
  protected   Hashtable allvalues = new Hashtable();
  protected   boolean	bRemoveViewObject = false;
  protected   boolean   bUseLineBreaks = true;
    
  /**
  *	Constructs object. Default rendering is combo box.
  */
  public PickList()
  {
  }

  public void setAllowNulls(boolean bSet)
  {
      bAddNullEntry = bSet;
  }

  public void setUseLineBreaks(boolean bUseBreaks)
  {
    this.bUseLineBreaks = bUseBreaks;
  }

  /**
  *	Tells picklist to render as a combo box.
  */
  public void useComboBox()
  {
    nType = TYPE_COMBOBOX;
  }

  /**
  *	Tells picklist to render as listbox
  */
  public void useListBox()
  {
    nType = TYPE_LISTBOX;
  }

  /**
  *	Tells picklist ot render as radio button group
  */
  public void useRadioGroup()
  {
    nType = TYPE_RADIO_GROUP;
  }

  /**
  *	Tells picklist ot render as checkbox group.
  */
  public void useCheckBoxGroup()
  {
    nType = TYPE_CHECKBOX_GROUP;
  }

  protected void prepareForMutliValueListGeneration()
  {
      Row    row = null;
      Row    rows[] = qView.getAllRowsInRange();
      
      String sValue;

      allvalues.clear();
      values.clear();
      
      if(this.bAddNullEntry)
      {
         allvalues.put("", "Null");
      }

      for(int i = 0; i < rows.length; i++)
      {
        if(rows[i].getAttribute(dataAttr) != null)
          sValue = rows[i].getAttribute(dataAttr).toString();
        else
          sValue = "";

        allvalues.put(sValue, "");
      }
      // split up the field value
      StringTokenizer tokens = new StringTokenizer(this.getValue() , ",");

      while(tokens.hasMoreElements())
      {
        values.put(tokens.nextToken(),"");
      }
  }

  protected HTMLElement generateComboBox()
  {
    try
    {
      HTMLSelect aSelect = new HTMLSelect(this.getFieldName());
      String sLabel;
      String sValue = "";
      Row rows[] = qView.getAllRowsInRange();

      System.out.println("Range Size=" + qView.getRangeSize());

      for(int i = 0; i < rows.length; i++)
      {
        Row row = rows[i];

        if(row.getAttribute(labelAttr) != null)
          sLabel = row.getAttribute(labelAttr).toString();
        else
          sLabel = "";

        if(row.getAttribute(dataAttr) != null)
          sValue = row.getAttribute(dataAttr).toString();
        else
          sValue = "";


        if(sValue.equals(this.getValue()))
        {
          aSelect.addSelectedOption(sLabel, sValue);
        }
        else
        {
          aSelect.addOption(sLabel , sValue);
        }
      }

      if(bAddNullEntry)
      {
         sValue = this.getValue();

         if(sValue == null || sValue.equals(""))
         {
            aSelect.addSelectedOption("", "");
         }
         else
         {
            aSelect.addOption("" , "");
         }
      }
      return aSelect;
    }
    catch(Exception ex)
    {
      throw new RuntimeException(ex.getMessage());
    }
  }

  protected HTMLElement generateListBox()
  {
    try
    {
      HTMLSelect aSelect = new HTMLSelect(this.getFieldName());
      String sLabel;
      String sValue = "";
      Row rows[] = qView.getAllRowsInRange();

      prepareForMutliValueListGeneration();

      for(int i = 0; i < rows.length; i++)
      {
        Row row = rows[i];
        
        if(row.getAttribute(labelAttr) != null)
          sLabel = row.getAttribute(labelAttr).toString();
        else
          sLabel = "";

        if(row.getAttribute(dataAttr) != null)
          sValue = row.getAttribute(dataAttr).toString();
        else
          sValue = "";

        if(values.get(sValue) != null)
        {
          aSelect.addSelectedOption(sLabel, sValue);
        }
        else
        {
          aSelect.addOption(sLabel , sValue);
        }
      }

      aSelect.setMultiple();

      if(aForm != null)
         aForm.addSelectField(this.getPromptText(), aSelect);
      return aSelect;
    }
    catch(Exception ex)
    {
      throw new RuntimeException(ex.getMessage());
    }
  }

  protected HTMLElement generateCheckBoxGroup()
  {
    try
    {
      String sLabel = "";
      String sValue;
      Row rows[] = qView.getAllRowsInRange();
      String sPromptText = getPromptText();
      HTMLElementContainer container = new HTMLElementContainer();

      prepareForMutliValueListGeneration();

      for(int i = 0; i < rows.length; i++)
      {
        Row row = rows[i];
        
        if(row.getAttribute(labelAttr) != null)
          sLabel = row.getAttribute(labelAttr).toString();
        else
          sLabel = "";

        if(row.getAttribute(dataAttr) != null)
          sValue = row.getAttribute(dataAttr).toString();
        else
          sValue = "";

        if(values.get(sValue) != null)
        {
          if(aForm != null)
          {
            aForm.addCheckBoxField(sPromptText, sLabel, getFieldName(), sValue, true);
          }
          else
          {
            HTMLInputElement input = new HTMLInputElement();

            input.setType("CHECKBOX");
            input.setChecked(true);
            input.setName(getFieldName());
            input.setValue(sValue);
            input.setLabel(sLabel);

            container.addElement(input);
            if(bUseLineBreaks)
               container.skipLine(1);
          }
        }
        else
        {
          if(aForm != null)
          {
            aForm.addCheckBoxField(sPromptText, sLabel, getFieldName(), sValue, false);
          }
          else
          {
            HTMLInputElement input = new HTMLInputElement();

            input.setType("CHECKBOX");
            input.setChecked(false);
            input.setName(getFieldName());
            input.setValue(sValue);
            input.setLabel(sLabel);

            container.addElement(input);
            if(bUseLineBreaks)
               container.skipLine(1);
          }
        }
        // clear the prompt text so it only gets generated once.
        sPromptText = null;
      }
      return container;
    }
    catch(Exception ex)
    {
      throw new RuntimeException(ex.getMessage());
    }
  }

  protected HTMLElement generateRadioGroup()
  {
   try
    {
      String sLabel = "";
      String sValue = "";
      Row rows[] = qView.getAllRowsInRange();
      HTMLElementContainer container = new HTMLElementContainer();
      
      String sPromptText = getPromptText();

      for(int i = 0; i < rows.length; i++)
      {
        Row row = rows[i];
        
        if(row.getAttribute(labelAttr) != null)
          sLabel = row.getAttribute(labelAttr).toString();
        else
          sLabel = "";

        if(row.getAttribute(dataAttr) != null)
          sValue = row.getAttribute(dataAttr).toString();
        else
          sValue = "";

        if(sValue.equals(this.getValue()))
        {
            if(aForm != null)
            {
               aForm.addRadioButtonField(sPromptText, sLabel, getFieldName(), sValue, true);
            }
            else
            {
               HTMLInputElement input = new HTMLInputElement();

               input.setType("RADIO");
               input.setChecked(true);
               input.setName(getFieldName());
               input.setValue(sValue);
               input.setLabel(sLabel);

               container.addElement(input);
               if(bUseLineBreaks)
               container.skipLine(1);
            }
        }
        else
        {
            if(aForm != null)
            {
             aForm.addRadioButtonField(sPromptText, sLabel, getFieldName(), sValue, false);
            }
            else
            {
               HTMLInputElement input = new HTMLInputElement();

               input.setType("RADIO");
               input.setChecked(false);
               input.setName(getFieldName());
               input.setValue(sValue);
               input.setLabel(sLabel);

               container.addElement(input);
               if(bUseLineBreaks)
               container.skipLine(1);
            }
        }
        // clear the prompt text so it only gets generated once.
        sPromptText = null;
      }

      if(bAddNullEntry && aForm != null)
      {
         boolean bSelected = false;
         
         if(this.getValue() == null || this.getValue().equals(""))
            bSelected = true;
            
         aForm.addRadioButtonField(null, Res.getString(Res.PROPT_NONE), getFieldName(), "", bSelected);
      }
      else if(bAddNullEntry)
      {
         boolean bSelected = false;
         
         if(this.getValue() == null || this.getValue().equals(""))
            bSelected = true;

         HTMLInputElement input = new HTMLInputElement();

         input.setType("RADIO");
         input.setChecked(bSelected);
         input.setName(getFieldName());
         input.setValue("");
         input.setLabel("None");

         container.addElement(input);
         if(bUseLineBreaks)
               container.skipLine(1);
      }
      return container;
    }
    catch(Exception ex)
    {
      throw new RuntimeException(ex.getMessage());
    }
  }

  /**
  *	  Defines the data source information for the picklist
  *
  *		@param	qView		The View object this list is bound to
  *		@param	labelAttr	The name of the attribute that provides the label values
  *		@param	dataAttr	The name of the attribute that provides the data values
  */
  public void setDataSourceInfo(RowSet qView , String labelAttr,  String dataAttr)
  {
    this.qView = qView;
    this.labelAttr = labelAttr;
    this.dataAttr = dataAttr;
	 this.bRemoveViewObject = false;
  }

  /**
  *	  Defines the data source information for the picklist
  *
  *		@param	appModule	The Application Module that is used to create the view object
  *		@param	sQuery		The SQL SELECT that retrieves the pciklist values or a ViewObject name
  *		@param	labelAttr	The name of the attribute that provides the label values
  *		@param	dataAttr	The name of the attribute that provides the data values
  */
  public void setDataSourceInfo(ApplicationModule appModule , String sQuery , String labelAttr,  String dataAttr)
  {
    try
    {
      // if it's already a view object, use it
      this.qView = appModule.findViewObject(sQuery);
    }
    catch(Exception ex)
    {
      qView = null;
    }

    if(qView == null)
    {
      this.qView = appModule.createViewObjectFromQueryStmt(null, sQuery);
      this.bRemoveViewObject = true;
    }
    else
    {
      this.bRemoveViewObject = false;
    }

    this.qView.setRangeSize(-1);
    
    this.labelAttr = labelAttr;
    this.dataAttr = dataAttr;
  }

  protected String getRenderedString()
  {
    String sText = "";
    HTMLElement elem = null;
    
    switch(nType)
    {
      case TYPE_COMBOBOX:
      {
        elem = generateComboBox();

        break;
      }
      case TYPE_LISTBOX:
      {
        elem = this.generateListBox();
        break;
      }
      case TYPE_CHECKBOX_GROUP:
      {
         elem = this.generateCheckBoxGroup();
        break;
      }
      case TYPE_RADIO_GROUP:
      {
         elem = this.generateRadioGroup();
        break;
      }
    }

    sText = elem.getAsString();

    return sText;
  }

  protected void initializeFromRenderingContext(HTMLRenderingContext ctx)
  {
      try
      {
         String sText;
         String sType = null;
         String sVOPath = null;
         String sDataAttribute = null;
         String sDisplayAttribute = null;


         if(ctx.userData.get("control_type") != null)
         {
            sType = ctx.userData.get("control_type").toString();
         }

         if(ctx.userData.get("lov_vo") != null)
         {
            sVOPath = ctx.userData.get("lov_vo").toString();
         }

         if(ctx.userData.get("data_attribute") != null)
         {
             sDataAttribute = ctx.userData.get("data_attribute").toString();
         }

         if(ctx.userData.get("display_attribute") != null)
         {
            sDisplayAttribute = ctx.userData.get("display_attribute").toString();
         }
         
         if(sVOPath == null || sType == null)
            return;
            
         // setup the type
         if(sType.equalsIgnoreCase("COMBOBOX"))
         {
            this.useComboBox();
         }
         else if(sType.equalsIgnoreCase("LISTBOX"))
         {
            this.useListBox();
         }
         else if(sType.equalsIgnoreCase("RADIOGROUP"))
         {
            this.useRadioGroup();
         }
          else if(sType.equalsIgnoreCase("CHECKBOXGROUP"))
         {
            this.useCheckBoxGroup();
         }

         DataWebBeanImpl dwb = new DataWebBeanImpl();
         dwb.initialize(ctx.page, sVOPath);

         RowSet rs = dwb.getRowSet();

         if(rs != null && sDataAttribute != null && sDisplayAttribute != null)
            setDataSourceInfo(rs , sDisplayAttribute, sDataAttribute);

      }
      catch(Exception ex)
      {
         throw new RuntimeException(ex.getMessage());
      }
  }
  
  public String renderToString(HTMLRenderingContext ctx , RowSet rs, Row row , String sAttribute)
   {
      try
      {
         String sText;

         initializeFromRenderingContext(ctx);

         //find the view object
         Object obj = row.getAttribute(sAttribute);
         AttributeDef aDef = rs.getViewObject().findAttributeDef(sAttribute);

         this.setAllowNulls(!aDef.isMandatory());
         
         this.setValue(obj.toString());
         this.sName = sAttribute;
         
         sText = getRenderedString();

         return sText;
      }
      catch(Exception ex)
      {
         throw new RuntimeException(ex.getMessage());
      }
   }
}

