/** 
 * This is the InputForm class.  It defines a widget that manages the input
 * of the data that controls the Grapher.
 */
PrtInputForm.prototype = new abstract_Widget();
function PrtInputForm() {
  this.intNumDivContainers = null;

  // - - Varable object properties:
  this.strHtml                = "";
  this.hshVisibleXYranges     = null;
  this.domVisibleXYranges     = null;
  this.strClickCode           = "";
  this.strRadioBtnClickCode   = "";
  this.strRenderAxesClickCode = "";
  this.strAboutClickCode      = ""; 
  this.strHelpClickCode       = ""; 
  this.strExitClickCode       = "";
  this.booInitiallyRendered   = false;
  // Methods:
  this.getHtml         = InputForm_getHtml;
  this.getData         = InputForm_getData;
  this.cleanReferences = InputForm_cleanReferences;
  /*-
   * The class constructor in this case is invoked as a method by extending
   * classes to inherit objects and other data that must be set upon instantiation.  This is an 
   * alternative way to implement inheritance in JS to the approach of using a single "getObjects" method.
   * It's suitable when the separate calls to the constructor as constructor and as 'this' method won't result 
   * in a lot of redundant code execution.
   */
  this.inputForm = InputForm;                                
  // Private Methods:
  /*-
   * All classes with a getHtml method are widgets.  However, this class is just one big
   * widget.  The input form that this widget manages is static (does not change once rendered), 
   * so we use private methods
   * instead of distinct widget clases: distinct widget classes are not needed in this case.
   */
  this.priGetVisibleRangeData      = InputForm_priGetVisibleRangeData;
  this.priGetEquationData          = InputForm_priGetEquationData;
  this.priSetHtml                  = InputForm_priSetHtml; 
  this.priGetEquationHtml          = InputForm_priGetEquationHtml;
  this.priGetGraphCorrespondInputs = InputForm_priGetGraphCorrespondInputs;
  this.priGetVisibleRangeInputHtml = InputForm_priGetVisibleRangeInputHtml;
  this.priGetAboutAndExitHtml      = InputForm_priGetAboutAndExitHtml;
}

// Static values:
  // Constants:
InputForm.RANGE_DIV  = "visiRange"; // Visible axes range input container.
// - - Equation entry boxes i.d.'s:
InputForm.EQ_ENTRY_DIV  = "equationInput";
InputForm.EQ_BOXES_DIV  = "entryBoxes";
InputForm.DOC_PATH_TO_ENTRY_BOXES = InputForm.EQ_ENTRY_DIV + ".document." + InputForm.EQ_BOXES_DIV + ".document.";
// - - Equation entry box i.d. nomenclature: 
InputForm.EQUATION      = "equation";
InputForm.EQ_SECTION    = "section";
// Scope assignment:
InputForm.prototype = new PrtInputForm();

/**
 * This is the class constructor of the InputForm class.
 * @param Either no parameters or all parameters below must be passed.
 * @param strEventReceiverMethod  A string representation of the identifier of the method  
 *                                to receive the events generated by the InputForm.
 * @param intNumDivContainers  The number of graphs on the display.
 * @param arrGraphColors  Contains a set of web-safe graph colors.
 */
function InputForm(intNumDivContainers, hshVisibleXYranges) {
  this.abstract_Widget(); // Invoke the superclass constructor here. 
  if (arguments.length == 0) { 
    /*-
     * This is being called to set the scope via a (static) prototype property.
     * This constructor will be called later as a method, with arguments.
     */
    return true;
  }
  if (arguments.length > 1) { // Then set defaults for the x y range input fields:
    this.hshVisibleXYranges = hshVisibleXYranges;
  } else {
    // -> Set ramge defaults:
    this.hshVisibleXYranges = new Object();
    this.hshVisibleXYranges[Grapher.MINX] = -10;
    this.hshVisibleXYranges[Grapher.MINY] = -10;
    this.hshVisibleXYranges[Grapher.MAXX] =  10;
    this.hshVisibleXYranges[Grapher.MAXY] =  10;
  }
  this.intNumDivContainers = intNumDivContainers;
  this.strRenderAxesClickCode = "window.top."+this.EVENT_RECEIVER_METHOD+"(\"RenderAxesAndGraphs\")";
  this.strHelpClickCode       = "window.top."+this.EVENT_RECEIVER_METHOD+"(\"Help\")";
  this.strAboutClickCode      = "window.top."+this.EVENT_RECEIVER_METHOD+"(\"About\")";
  this.strExitClickCode       = "window.top."+this.EVENT_RECEIVER_METHOD+"(\"Exit\")";

  this.domVisibleXYranges = new Object();
  this.domVisibleXYranges[Grapher.MINX] = null;
  this.domVisibleXYranges[Grapher.MINY] = null;
  this.domVisibleXYranges[Grapher.MAXX] = null;
  this.domVisibleXYranges[Grapher.MAXY] = null;
  this.priSetHtml();    
}


/**
 * This method returns the HTML required to render the input form. 
 * @return string (see above).
 */
function InputForm_getHtml() {
  return this.strHtml;
}


/** 
 * This method is always overridden by the extending class.  It must be 
 * overloaded to support both getting the data for a particular equation to be 
 * graphed and getting the data that specified the range of the visible
 * graph axes to display. 
 * @param OPTIONAL intEquationNumber  * If this parameter is not passed, getData returns the
 *                                      data specifying the visible range of the graph axes.
 *                                    * This parameter, if passed, specifies which equatioh 
 *                                      to get the data for (for example, in the case of a polynomial, it 
 *                                      would return the coefficients in an array).
 * @return objXYRange if no parameter passed (see InputForm_priGetVisibleRangeData).
 * @return anyValue   (if intEquationNumber is passed) This is specified by the method in the 
 *                    extending class that overrides this method.
 */
function InputForm_getData(intEquationNumber) {
  if (arguments.length == 0) {
    return this.priGetVisibleRangeData();
  } else {
    alert("Supposed to get data from equation boxes.");
  }
}


/*   -   -   -   -   -   -   -   Private Methods:       */

/**
 * This method returns the data that specifies the range of the graph
 * axes to display. 
 * Note that we pass the containing document i.d. (InputForm.RANGE_DIV+".document.") in case some platform needs that.
 * @return objXYRange  An object containing the data described above.
 */
function InputForm_priGetVisibleRangeData() {
  if (this.booInitiallyRendered)  { // The DOM object exists, so update the values according to the DOM:  
    // We use the "null" check to avoid unnecessary calls to "getReferenceToDocProperty".
    if (this.domVisibleXYranges.minX == null) { 
      this.domVisibleXYranges.minX = 
        GloScope.CrossPlatformCode.getReferenceToDocProperty(window.top.input, 
                                                             (InputForm.RANGE_DIV+".document."+Grapher.MINX) );
    }
    if (this.domVisibleXYranges.maxX == null) {
      this.domVisibleXYranges.maxX = 
        GloScope.CrossPlatformCode.getReferenceToDocProperty(window.top.input, 
                                                             (InputForm.RANGE_DIV+".document."+Grapher.MAXX) );
    }
    if (this.domVisibleXYranges.minY == null) {
      this.domVisibleXYranges.minY = 
        GloScope.CrossPlatformCode.getReferenceToDocProperty(window.top.input, 
                                                             (InputForm.RANGE_DIV+".document."+Grapher.MINY) );
    }
    if (this.domVisibleXYranges.maxY == null) {
      this.domVisibleXYranges.maxY = 
        GloScope.CrossPlatformCode.getReferenceToDocProperty(window.top.input, 
                                                             (InputForm.RANGE_DIV+".document."+Grapher.MAXY) );
    }
    this.hshVisibleXYranges[Grapher.MINX] = parseFloat(this.domVisibleXYranges.minX.value);
    this.hshVisibleXYranges[Grapher.MAXX] = parseFloat(this.domVisibleXYranges.maxX.value);
    this.hshVisibleXYranges[Grapher.MINY] = parseFloat(this.domVisibleXYranges.minY.value);
    this.hshVisibleXYranges[Grapher.MAXY] = parseFloat(this.domVisibleXYranges.maxY.value);
  }
  return this.hshVisibleXYranges;
} //-InputForm_priGetVisibleRangeData


/** 
 * This method is always overridden by the extending class.  Its purpose is to 
 * return the data corresponding to the equation specified by 'intEquationNum'.
 * @intEquationNum  An number identifying an equation that corresponds to a graph on
 *                  the screen.
 * @return anyValue  The return value varies according to the extending class.  It 
 *                   only meet the requirement of the concrete equation class.
 */
function InputForm_priGetEquationData(intEquationNum) {
  return (
            "To help you in writing your overriding _priGetEquationData method, here's the path to find the data: \n"  
            + InputForm.DOC_PATH_TO_ENTRY_BOXES
         );
}


/**
 * This method returns the static HTML needed to construct the input form.
 * See the comment in the superclass.
 * @strEquationInput  The HTML for the input cells for the specific eqaution being plotted.
 */
function InputForm_priSetHtml() {
  // Insert the fields into an HTML form:
  this.strHtml = 
      " \n <form id='graphInput' name='graphInput'> " 
    + this.priGetGraphCorrespondInputs() + this.priGetVisibleRangeInputHtml() + this.priGetAboutAndExitHtml()
    + " \n </form>";
} //-priSetHtml


/** 
 * This is a private method for getting the HTML markup needed for all inputs
 * that correspond on a 1-1 basis with the individual graphs on the display.
 # @return  The string containing the Html as described above.
 */
function InputForm_priGetGraphCorrespondInputs() {
  var strBtnHtml;
  var strRadioBtnHtml;
  /*-
   * We formulate the markup for 
   *   a) the set of boxes that hold the equation input value and the "Plot"-it button 
   * and 
   *   b) the set of boxes that hold the radio buttons for which graph to bring to the front
   * together, because they both exist in a 1 to 1 ratio with the graph layers (div's) on the screen.
   */
  // Opening markup:
  strBtnHtml     = "\n <div  id='" + InputForm.EQ_ENTRY_DIV + "' > \n "
    + "           Enter the values for the left-hand side of any equation or JavaScript function where f(x)=y below"
    + "           and click 'Plot #x' to see it plotted. \n "
    + "     <div  id='" + InputForm.EQ_BOXES_DIV + "'  >  \n "
    + "       <table> \n <tr> \n ";
  strRadioBtnHtml = "  <div  id='toFront'> \n  "
    + "           Click a radio button below to select a graph to bring to the front: "
    + "     <div  id='toFrontBoxes' >  \n "
    + "       <table> <tr> \n ";
  // Compose the markup for parts that correspond to individual graphs on the screen:
  for (var intI=0; intI<this.intNumDivContainers; intI++) {
    this.strClickCode  = "window.top."+this.EVENT_RECEIVER_METHOD+"("+intI+")";
    this.strRadioBtnClickCode = "window.top."+this.EVENT_RECEIVER_METHOD+"("+(intI+5000)+")";
    strBtnHtml   += " <td  class='plotBtnTD'> \n "
      + this.priGetEquationHtml(intI)
      + "      <input type='button' value='Plot #"+intI+"' "
      + "             onclick='eval("+this.strClickCode+")' "
      + "             style='color: #000000; font-size: 14pt; background-color: "
      +               this.GRAPH_COLORS[intI]+"; ' >  \n "
      + " </td> \n ";
    strRadioBtnHtml += " <td class='rdoBtnTD'> \n "
      + "   <input  type='radio'  name='whichDivInFront'  id='whichDivInFront'  value='Graph"
      +             intI + "'  style='color: #000000; background-color: "
      +             this.GRAPH_COLORS[intI] + "; '  onclick='eval("+this.strRadioBtnClickCode+")' > \n "
      + "           Graph #"+intI+" &nbsp; &nbsp; \n "
      + " </td> \n ";
    if ( (intI+1)%4 == 0 ) {
      strBtnHtml += " </tr> \n <tr> \n ";
    }
    if ( (intI+1)%5 == 0 ) {
      strRadioBtnHtml += " </tr> \n  <tr> \n ";
    }
  }
  // Closing markup:
  strBtnHtml += " </tr> \n </table> \n </div> \n </div> \n ";
  strRadioBtnHtml += " </tr> \n </table> \n </div> \n  </div> \n ";
  return (strBtnHtml + strRadioBtnHtml);
}


/** 
 * This is a method for getting the HTML markup need for the visible-range input.
 * @return  String containing the Html as described above. 
 */
function InputForm_priGetVisibleRangeInputHtml() {
  return (
            " <div id='"+InputForm.RANGE_DIV+"'  title='Tip -> Use this as a zoom-" 
          + "in / zoom-out feature by keeping ratios constant and replotting.'      "
          + " > "
          + "   Enter the range of the visible portion of the axes, and then click 'Render Axes' "
          + "   (clears all graphs)."
          + "      <table  class='vrTABLE'> "
          + "       <tr> <td  class='vrTD'> "
          + "          Minimum 'x' coordinate to show: "
          + "          </td><td  class='vrTD'> "
          + "          <input  type='text'  id='"+Grapher.MINX+"'  size='11' maxlength='11'  value='"
          +                    this.hshVisibleXYranges[Grapher.MINX] + "' "
          + "                  class='vrINPUT' > "
          + "        </td> </tr>"
          + "        <tr>   <td  class='vrTD'> "
          + "          Maximum 'x' coordinate to show: "
          + "        </td><td  class='vrTD'> " 
          + "          <input  type='text'  id='"+Grapher.MAXX+"'  size='11' maxlength='11'  value='"
          +                    this.hshVisibleXYranges[Grapher.MAXX] + "' "
          + "                  class='vrINPUT' > "
          + "        </td></tr> "
          + "        <tr>  <td  class='vrTD'> "
          + "          Minimum 'y' coordinate to show: "
          + "        </td> <td  class='vrTD'> "
          + "          <input  type='text'  id='"+Grapher.MINY+"'  size='11' maxlength='11'  value='"
          +                    this.hshVisibleXYranges[Grapher.MINY] + "' "
          + "                  class='vrINPUT'> "
          + "        </td></tr> "
          + "        <tr>  <td class='vrTD'> "
          + "          Maximum 'y' coordinate to show: "
          + "        </td><td  class='vrTD'> "
          + "          <input  type='text'  id='"+Grapher.MAXY+"'  size='11' maxlength='11'  value='"
          +                    this.hshVisibleXYranges[Grapher.MAXY] + "' "
          + "                  class='vrINPUT' > "
          + "        </td> </tr> "
          + "      </table> "
          + "   <div  id='renderAxesBox' >"
          + "         <input type='button' id='RenderAxes'  value='Render Axes' "
          + "                onclick='eval("+this.strRenderAxesClickCode+")' >  \n "
          + "   </div>"
          + " </div> "
          );    
} //-getVisibleRangeInputHtml


/** 
 * This is an inner function for getting the HTML markup needed for the 
 * 'About' and 'Exit' buttons (and any other misc. buttons) that come 
 * at the bottom of the input display.
 * @return  A string containing the markup described above.
 */
function InputForm_priGetAboutAndExitHtml() {
  return ( 
       "  <div  id='miscBtnBox' class='miscBtnBox'>"
     + "      <input type='button' id='aboutBtn' class='miscBtn' value='About/Purchase the Code' "
     + "             onclick='eval("+this.strAboutClickCode+")'  >  \n "
     + "      <input type='button' id='helpBtn'  class='miscBtn' value='Help' "
     + "             onclick='eval("+this.strHelpClickCode+")'   >  \n "
     + "      <input type='button' id='exitBtn'  class='miscBtn' value='Free Memory and Exit' "
     + "             onclick='eval("+this.strExitClickCode+")'  >  \n "
     + "  </div>"
  );
}


/** 
 * This method is always overridden by the extending class.
 * @intEquationNum  An number identifying an equation that corresponds to a graph on
 *                  the screen.
 */
function InputForm_priGetEquationHtml(intEquationNum) {
  return "OverrideWithCustomHTML"+intEquationNum;
}


/** 
 * If there are any circular reference points besides
 * this.domVisibleXYranges, then this method must 
 * be overridden by extending classes if in 
 * order to ensure against memory leaks.
 */
function InputForm_cleanReferences() {
  // Clean references to each visible-range input box:'
  this.domVisibleXYranges = null;
  // Clean references to each equation-input box.
}









