/** 
 * This is the Grapher class.  This file contains the 'main' method that 
 * activates the Grapher package.  It manages the actual drawing of the graph itself and the 
 * plotted points of the 2-dimensional image on the screen.
 */ 
function PrtGrapher() {
  // -- Here are declared the major components of the Grapher API that are managed by the Grapher class:
  this.objInputForm = null;
  this.objGraph = null;
  this.objTextDisplay = null;
  this.objEquation = null;
  // -- -- -- -- -- -- -- -- 
  this.intGraphHeight = 500; // units: pixels.
  this.intGraphWidth  = 500; // units: pixels. 
  this.docCanvas = null;
  this.docInput  = null; 
  this.intCurrentDivContainer = -1;
  this.strCurrentCurveType = "";

  /*-
   * The following two values represent the positions that the 
   * X and Y axes must be set at in order to conform to the X and Y axis ranges 
   * specified in the input form.  
   */   
  this.intYaxisLeft = 0; 
  this.intXaxisTop  = 0;
  // Methods: 
  this.initialRender = Grapher_initialRender;
  this.plot          = Grapher_plot;
  this.receiveEvent  = Grapher_receiveEvent; 
  this.priGetObjects = PrtGrapher_priGetObjects;  // For inheritance purposes only. 
}


/**
 * This method bestows unique copies of objects upon extending classes.
 */
function PrtGrapher_priGetObjects() {
  this.hshSupportedEquationTypes = new Object();
  // deprecated: this.hshSupportedEquationTypes["polynomial"] = "Polynomial";
  this.hshSupportedEquationTypes["FofX"] = "FofX";
  this.arrRawResults = new Array();
  this.hshVisibleXYranges = new Object();
  this.hshVisibleXYranges[Grapher.MINX] = -10;
  this.hshVisibleXYranges[Grapher.MINY] = -10;
  this.hshVisibleXYranges[Grapher.MAXX] =  10;
  this.hshVisibleXYranges[Grapher.MAXY] =  10;
}

// Static properties:
// Show-axes range i.d.'s:
Grapher.MINX = "minX";
Grapher.MINY = "minY";
Grapher.MAXX = "maxX";
Grapher.MAXY = "maxY";  
Grapher.prototype = new PrtGrapher(); // Below: fun with dynamic writing:
Grapher.strAbout =   "<div  id='aboutDiv' >"
                   + "<br> <p class='title'> <h2>'Compare-the-Graphs'</h2> "
                   + "version 1.0 </p> "
                   + "<p class='byLine'>  by Christopher M. Balz.&nbsp; <br>Copyright &copy; 2002 TreeLogic Software Engineering. </p> <br><br>" 
                   + "<a href='./doc/jsdoc/index.html' target='_blank'>Browse the JavaScriptdoc Documentation!</a><br><br>"
                   + "<b>Businesses</b>: <ul><li><b>Commercial License</b>: The complete source code and its use for any legal purpose by a "
                   + "single commercial entity is "
                   + "available without "
                   + "any warranty (express or implied) "
                   + "for commercial " 
                   + "use and commercial modification (includes use by non-profit corporations) for $400.00 (United States dollars)." 
                   + "&nbsp; This constitutes the Commercial License for 'Compare-the-Graphs'. <span style='color: red;'>"
                   + "Unauthorized use of this code will result in " 
                   + "prosecution to the full extent of the law.</span><br><br>"
                   + "<div style='padding-top:10px; border-style: solid; border-width: 2px; text-align: center;'>"
                   + "Commercial License: U.S. $400.00<br>"

+ "<form action=\"https://www.paypal.com/cgi-bin/webscr\" method=\"post\">"
+ "<input type=\"hidden\" name=\"cmd\" value=\"_xclick\">"
+ "<input type=\"hidden\" name=\"business\" value=\"chris@treelogic-swe.com\">"
+ "<input type=\"hidden\" name=\"item_name\" value=\"Commercial License for Compare-the-Graphs Software Program and Source "
+ "Code for Commercial Use\">"
+ "<input type=\"hidden\" name=\"item_number\" value=\"TLSWE-0\">"
+ "<input type=\"hidden\" name=\"amount\" value=\"400.00\">"
+ "<input type=\"hidden\" name=\"no_note\" value=\"1\">"
+ "<input type=\"hidden\" name=\"currency_code\" value=\"USD\">"
+ "<input type=\"hidden\" name=\"lc\" value=\"US\">"
+ "<input type=\"image\" src=\"https://www.paypal.com/images/x-click-but23.gif\" border=\"0\" name=\"submit\" "  
+ "alt=\"Make payments with PayPal - it's fast, free and secure!\">"
+ "</form>"

+ "<center>"
+ "<a href=\"http://seals.squaretrade.com/cW099/742939631.map\" target=\"_blank\">"
+ "<img ismap src=\"http://seals.squaretrade.com/cW099/742939631.gif\" alt=\"Building Trust in Transactions (tm)\" border=0>"
+ "</a>"
+ "</center>"
                   + "<br></div><br>"                     
                   + "</li>" 
                   + "<li> TreeLogic Software Engineering can modify this code to suit your exact needs -- "
                   + "<a href='mailto:chris@treelogic-swe.com'>contact us</a>.</li></ul>"

                   + "<br><b>Click to get the code</b>: choose either the "
                   + "<ul><li><a href='ftp://anonymous@fmrfreek.best.vwh.net/"
                   + "Grapher.tar.gz'>"
                   + "Grapher.tar.gz file</a> (For '.tar.gz' files: at the command line, enter 'tar xvzf Grapher.tar.gz' to unpack)" 
                   + "</li> <li> or the "
                   + "<a href='ftp://anonymous@fmrfreek.best.vwh.net/"
                   + "Grapher.zip'>"
                   + "Grapher.zip file.</a></li></ul>"
                   + "<br><b>Contact</b>: <ul><li><a href='mailto:chris@treelogic-swe.com'> "
                   + " chris@treelogic-swe.com </a> </li><li>" 
                   + "Alternate e-mail address: <a href='mailto:christophermbalz@stanfordalumni.org'> "
                   + "christophermbalz@stanfordalumni.org</a> </li></ul>"

                   + "<br><p><b>Description</b>: This is an application written in JavaScript and HTML that runs completely"
                   + " on the client computer.&nbsp;  All code (logic and markup) for this application resides or is "
                   + "dynamically generated on the client.&nbsp; The application"
                   + " is for drawing graphs "           
                   + "on a user agent, as a component of another software application or as itself a Web service, "
                   + "accessible from any supported user agent "
                   + "(Web browser) that reasonably implements the standards of the World Wide Web Consortium for HTML, DOM, and CSS, and "
                   + "that reasonably implements the standards of the ECMA for JavaScript 1.2+." 
                   + "&nbsp; Currently, this means Internet Explorer 5+ on Windows and Netscape 6.1+/Mozilla 1.0+ on Mac, Linux/Unix."
                   + "<br><br>Through the 'Grapher' package, this application provides a well-documented, generalized, very extensible "
                   + "object-oriented API, written in JavaScript compatible with JS versions 1.2 through 1.5, "
                   + "for drawing any kind of 2-dimensional graph.&nbsp; The Grapher package is currently "
                   + "ported to any equation or function in two variables. </p> "
                   + "<p><b>Notice</b>: This software is copyright &copy; 2002 TreeLogic Software "
                   + "Engineering.  Whether purchased or obtained for free, this code is provided WITHOUT WARRANTY "
                   + "either expressed or implied.&nbsp; "
                   + "Free Use: You may study, use, modify, and distribute it free of charge for any "
                   + " <i>COMPLETELY NON-COMMERCIAL</i> purpose, "
                   + "as long as this Notice is retained.&nbsp; <span style='color: red;'>Unauthorized use of this code will result in " 
                   + "prosecution to the full extent of the law.</span>"
                   + "</div>";
Grapher.strAboutStyle = " <link href='./static/css/about.css' rel='stylesheet' type='text/css'> ";


/**
 * This is the class constructor for the Grapher class. 
 * @param  strEquationType  A string that corresponds to the identifier name of the class constructor
 *                          for the equation to be graphed.
 */
function Grapher(strEquationType) {
  this.priGetObjects(); // Inherit unique copies of all objects from the prototype/abstract class.
  this.strEquationType = strEquationType;
  if (this.hshSupportedEquationTypes[this.strEquationType] == null) {
    alert("Error: the equation type specified in web_graph.html is not supported.");
  }
  var strToEval = "new " + (this.hshSupportedEquationTypes[this.strEquationType])
    + "InputForm("+Graph.intNumCurvesPossible+", this.hshVisibleXYranges);";
  this.objInputForm = eval(strToEval);
  var strConstructorCall = "new "+(this.hshSupportedEquationTypes[this.strEquationType])
      +"(this.objGraph, this.objInputForm, this.objTextDisplay);";
  this.objTextDisplay = new TextDisplay();
  this.objGraph    = new Graph(this.intGraphWidth, this.intGraphHeight, this.objInputForm);
  // Debug: alert(strConstructorCall);
  this.objEquation = eval(strConstructorCall);
  this.initialRender();
}


/**
 * This method handles the initial rendering of all the elements that need to be on the 
 * screen at start-up of the application.
 */
function Grapher_initialRender() {
  this.docCanvas = window.top.canvas.document;
  this.docInput  = window.top.input.document;
  var arrCanvasHtml = new Array();
  var arrInputFormHtml = new Array();
  var strInputFormHtml = "";
  var strCanvasHtml = "";
  var strFinalHtml;

  arrCanvasHtml[arrCanvasHtml.length] = this.objGraph.getHtml();
  arrCanvasHtml[arrCanvasHtml.length] = this.objTextDisplay.getHtml();
  arrInputFormHtml[arrInputFormHtml.length] = this.objInputForm.getHtml();
  strCanvasHtml =  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"> \n <html> "
    + "<head> <link href='./static/css/canvas.css' rel='stylesheet' type='text/css'> </head>"
    + "<body> \n "
    + arrCanvasHtml.join(" ")
    + " \n </body> </html>";
  // alert(" strCanvasHtml:\n" + strCanvasHtml); // debug.
  strInputFormHtml =  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"> \n <html> "
    + "<head> <link href='./static/css/input.css' rel='stylesheet' type='text/css'> </head>"
    + "<body> \n "
    + arrInputFormHtml.join(" ")
    + " \n </body> </html>";
  this.docCanvas.open();
  this.docCanvas.write(strCanvasHtml); 
  this.docCanvas.close(); 
  this.docInput.open();
  // alert(strInputFormHtml);
  this.docInput.write(strInputFormHtml);
  this.docInput.close();
  this.objInputForm.booInitiallyRendered = true;
}


/**
 * This method puts the points of an equation on the screen.
 * @param arrRawResults  The array of raw math results that the equation produced.
 * @param intCurrentDivContainer  The container that the plotting will happen in.
 */
function Grapher_plot(arrRawResults, intCurrentDivContainer) {
  var anyI;
  this.intCurrentDivContainer = intCurrentDivContainer; 
  var arrCoords = new Array();
  var hshVisibleXYranges = this.objInputForm.getData();
  var intXMin = hshVisibleXYranges[Grapher.MINX];
  var intYMin = hshVisibleXYranges[Grapher.MINY];
  var intXMax = hshVisibleXYranges[Grapher.MAXX];
  var intYMax = hshVisibleXYranges[Grapher.MAXY];
  var funResultPair = function(intX, intY) { 
    this.intX = intX;
    this.intY = intY;
  }
  for (var intI=0; intI<arrRawResults.length; intI++) {
    // If coordinate pair is plottable on the graph, convert coordinates to plottable integers:
    if  (
         (Math.round(arrRawResults[intI].intX) <= intXMax) 
         && 
         (Math.round(arrRawResults[intI].intX) >= intXMin) 
         )
      {
        for (anyI in arrRawResults[intI].hshY) {
          if ( (Math.round(arrRawResults[intI].hshY[anyI]) <= intYMax) 
               && 
               (Math.round(arrRawResults[intI].hshY[anyI]) >= intYMin)
               )             
            {
              arrCoords[arrCoords.length] = 
                new funResultPair(arrRawResults[intI].intX, arrRawResults[intI].hshY[anyI]);
            }
        }
      }
  } //-for loop
  this.arrPlotCoordinates = arrCoords;
  this.objGraph.plotOnGraph(this.intCurrentDivContainer, arrCoords);
}


/**
 * This method receives all the events coming from the user.
 * @param  anyId  An integer or string code that indicates the action to be taken by the application.
 */
function Grapher_receiveEvent(anyId) {
  var intId;
  var strOptions;
  switch (anyId) {
  case "RenderAxesAndGraphs" : 
    var hshMaxMinAxesRanges = this.objInputForm.getData();
    this.objGraph.renderAxes(hshMaxMinAxesRanges);
    break;
  case "Exit" : // Remove JS to DOM References of container div's, which contain graph axes/labels, and plot div points.
    this.objTextDisplay.cleanReference();
    this.objGraph.cleanReferences();
    this.objInputForm.cleanReferences();
    alert("Memory freed for release by the browser.  Goodbye!");
    break;
  case "ClearTextOutput" : this.objTextDisplay.clear();
    break;
  case "About" :
    strOptions = "width=500,height=650,screenX=100,screenY=100,location=no,status=no,menubar=yes,directories=no,scrollbars=yes,resizable=yes";
    GloScope.winAbout = window.open("", "AboutCompareTheGraphs", strOptions);
    var strHtml = "<html> <head> <title> About Compare-the-Graphs </title> "+Grapher.strAboutStyle
      +" </head> <body bgcolor='#000000' color='#FFFF00'> "+Grapher.strAbout+" </body> </html> ";
    GloScope.winAbout.focus();
    GloScope.winAbout.document.open();
    GloScope.winAbout.document.write(strHtml);
    GloScope.winAbout.document.close();
    break;
  case "Help" :
    strOptions = "width=700,height=650,screenX=200,screenY=100,location=yes,menubar=yes,toolbar=yes,directories=no,"
      +"resizable=yes,scrollbars=yes";
    GloScope.winHelp = window.open('./static/help.html', "HelpForCompareTheGraphs", strOptions);
    GloScope.winHelp.focus();
  default : 
    intId = parseInt(anyId);
    break;
  }

  if ( (intId < Graph.intNumCurvesPossible) && (intId >= 0) ) {  // Otherwise, it is the "Exit" button.
    this.plot(this.objEquation.getRawResults(intId), intId);
  } else if (intId >= 5000) { // A div has been selected to be brought to the front.
    this.objGraph.setInFront(intId-5000);
  } 
}

/* - - - - - - - - - - - - */

/*- 
 * This function is called from onload() in the HTML body tag.  If desired, the server can thus
 * insert arguments by dynamically generating the HTML page that includes this JavaScript file,
 * inserting the arguments in the call from 'onload'.  An example of this type of argument 
 * would be the type of curve to draw.
 * @param arrArguments  An array containing at element zero the type of curve to be specified by 
 *                      the user and drawn.  Presently, 'FofX' is the only type supported.
 */
function main(arrArguments) {
  // We make objGrapher explicitly a global object by putting it in our 'corral' for global objects.
  /*-
   * NN4.x requires GloScope to be explicitly set to window.top (although it is already implicitly, 
   * since it's in the global scope) so that it may be accessible from the event handler.
   */
  window.top.GloScope.objGrapher = new Grapher(arrArguments[0]); 
  strMessage = GloScope.CrossPlatformCode.getListSupportedPlatforms()
    +"\n\n You are currently running: \n"+GloScope.CrossPlatformCode.getPlatform();
  alert(strMessage);
  // debugger;
  alert( (GloScope.CrossPlatformCode.getPlatformBugAdvisory()) );
}






