// (c) J. Dean Brock, Rebecca F. Bruce, 2001, 2003, 2004, 2007, 2008
// Department of Computer Science
// University of North Carolina at Asheville

// Derived from UNCA CSCI 201 Plot-2D lab
// (c) J. Dean Brock, 1998


// If you are solving this lab, you should ignore everything
// down the comment that says:
// ***   START YOUR WORK HERE   ***
// Well, we really mean the next comment that says that.

public class Plot2D {
    
  // Constants to control the window size
  final static int numPoints  = 256 ;
  final static double delta   = 1.0/numPoints ;
  final static int plotSize   = 2*numPoints + 1 ;
  final static int borderSize = 20 ;
  final static int windowSize = plotSize+2*borderSize ;
  final static int zeroPoint  = windowSize/2 ;
  
  // This will test the method
  //    c -- Plot2D.class   * needed for reflection
  //    o -- new Plot2d()   * needed for reflection
  //    m -- name of method as a string
  //    t -- title for the plit
  // This method will "hang" if the tested method loops
  static void testMethod(Class<Plot2D> c, Plot2D o, String m, String t) {
    double[] results = null ;
    System.out.println("Running plot " + m) ;
    try {
      java.lang.reflect.Method mRef 
        = c.getDeclaredMethod(m, double.class) ;
      results = runMethod(o, mRef) ;
    } catch (NoSuchMethodException nsme) {
      System.err.println("Unable to find method: " + m + "(double)") ;
      return ;
    }

    if (results != null) {
      displayResults(results, t) ;
    }
  }
  
  // This will generate an array of values to be plotted
  static double[] runMethod(Plot2D oRef, java.lang.reflect.Method mRef) {
    double[] results = new double[plotSize] ;
    for(int xInd = 0; xInd<results.length; ++xInd) {
      double x = -1 + xInd*delta ;
      try {
        // In case of loop -- uncomment the next line
        // System.out.println("  Calling at " + x) ;
        double y = (Double) mRef.invoke(oRef, x) ;
        if (y<-1 || y>1) {
          System.err.println("  Problem with call at " + x) ;
          return null ;
        } else {
          results[xInd] = y ;
        }
      } catch (Exception e) {
        System.err.println("  Problem with call at " + x) ;
        System.err.println("  Exception " + e) ;
        return null ;
      }
    }
    return results ;
  }
  
  static void displayResults(double[] yValues, String t) {
    Picture p = new Picture(windowSize, windowSize) ;
    java.awt.Graphics g = p.getGraphics() ;
    g.setColor(java.awt.Color.ORANGE) ;
    g.drawRect(borderSize, borderSize, plotSize, plotSize) ;
    g.drawLine(zeroPoint, borderSize, zeroPoint, windowSize-borderSize) ;
    g.drawLine(borderSize, zeroPoint, windowSize-borderSize, zeroPoint) ;
    int lastX = borderSize ;
    int lastY = zeroPoint - (int)Math.round(yValues[0]*numPoints) ;
    int presX = borderSize ;
    g.setColor(java.awt.Color.GREEN) ;
    for (int i=1; i<yValues.length; ++i) {
      int nextY = zeroPoint - (int)Math.round(yValues[i]*numPoints) ;
      g.drawLine(lastX, lastY, lastX+1, nextY) ;
      lastY = nextY ;
      ++lastX ;
    }
    p.show() ;
    p.setTitle(t) ;
  }

// main method
  public static void main(String[] args) {
    Class<Plot2D> classInfo = Plot2D.class ;
    Plot2D          objectP = new Plot2D() ;
 
    int numPlots = 9 ;
    String[] methods = new String[numPlots] ;
    String[] titles  = new String[numPlots] ;
    for (int i=0; i<numPlots; ++i) {
      methods[i] = "plot" +  (i+1) ;
      titles[i]  = "Plot " + (i+1) ;
    }
    
    for (int i=0; i<methods.length; ++i) {
      testMethod(classInfo, objectP, methods[i], titles[i]) ;
    }
  }   

  // ***   START YOUR WORK HERE   ***
  
  // Plot 1
  static double plot1(double x) {
    return x ;
  }
  
  // Plot 2
  static double plot2(double x) {
    return x*x ;
  }
  
  // Plot 3
  static double plot3(double x) {
    return x*x*x ;
  }
  
  // Plot 4
  static double plot4(double x) {
    return x*x*x*x ;
  }
  
  // Plot 5
  static double plot5(double x) {
    return x*x*x*x*x ;
  }
  
  // Plot 6
  static double plot6(double x) {
    return x*x*x*x*x*x ;
  }
  
  // Plot 7
  static double plot7(double x) {
    return x*x*x*x*x*x*x ;
  }
  
  // Plot 8
  static double plot8(double x) {
    return x*x*x*x*x*x*x*x ;
  }
  
  // Plot 9
  static double plot9(double x) {
    return x*x*x*x*x*x*x*x*x ;
  }
  
}
