package FOExperiment;

import java.awt.*; 
import java.awt.event.*;

/*###################################################*/
public class BoxShoot extends Canvas implements Runnable{ 
  int dY,dX; 
  Thread drawThread;
  Image offScrImg;
  Circle ball;
  int radius;
  boolean initCanvas=true;

  FallingObject parent=null;

  int nDrops;
  int frameRate;
  double deltaT;
  double speedUp;
  double gPhysical;
  double physicalHeight;

/*--------------------------------------------------*/ 
// 
  public BoxShoot(int nDrops, double speedUp, double grav,
                  double elevation, FallingObject fo){

    parent = fo;

    this.nDrops = nDrops;

    setBackground(Color.white);
    dY=240; 
    dX=150; 
    setSize(dX,dY);

    // Choose some parameter for the object to drop
    radius = dY/20;

    // These parameters separate thread animation
    // frame rates from the physical time of the 
    // falling object. 
    frameRate = 10;
    this.speedUp = speedUp;

    gPhysical = grav;// = 9.8cm/s**2
    physicalHeight = elevation;
    init();
  }
/*--------------------------------------------------*/ 
  public Dimension getPreferredSize(){
    return new Dimension(dX,dY);
  }
/*--------------------------------------------------*/ 
// 
  public void init(){ 

    deltaT = frameRate/1000.0;
    deltaT *= speedUp;

    // Scale physical g units to the graphical pixel units
    // Let the frame represent a 200cm in height.
    double g = gPhysical * ( dY/physicalHeight);

    // Create the object to drop
    int x0 = 2 * radius;
    int y0 = 2 * radius;
    ball = new Circle(x0,y0,radius,dX,dY,g);

    // set it's initial velocity
    ball.VxInit   = 0.0;
    ball.VyInit   = 0.0;

}
/*--------------------------------------------------*/ 
  public void start() { 
    if (drawThread != null){ 
      stop();
    } 
    init();
    ball.reset();
    initCanvas=true;
    drawThread = new Thread(this);    
    drawThread.start();
  }
/*--------------------------------------------------*/ 
  public void stop() { 
    drawThread = null;
    // Give this thread time to jump out of its loop in run()
    try { 
      Thread.sleep(250); 
    } catch (InterruptedException e)
    {} 
  }
/*--------------------------------------------------*/ 
  public void run() { 
    repaint();
    while (drawThread != null) { 
      // Use sleep to pause between movements
      try { 
        Thread.sleep(frameRate); 
      } catch (InterruptedException e)
      {} 
      // If all movement stopped then stop animation
      if( ball.xStop && ball.yStop){
        stop();
        break;
      }

      ball.move(deltaT); 
      repaint();

      // Send sensor readings
      parent.detector.sensor(ball.y,frameRate);

    }
    parent.dropDone();
  }
/*--------------------------------------------------*/ 
  public synchronized void update( Graphics g ) {
    // Create an offscreen image and then get its graphics context
    if ( offScrImg == null )
      offScrImg = createImage( dX, dY );
    Graphics og = offScrImg.getGraphics();

    // Now draw on the offscreen image.
    paint( og );

    // Don't bother to call paint, just draw the offscreen image
    // to the screen.
    g.drawImage(offScrImg, 0, 0, this);

    // Get rid of the offscreen graphics context. Can't unclip a graphics
    // context so have to get a new one next time around.
    og.dispose();
  }
/*--------------------------------------------------*/ 
  public synchronized void paint(Graphics g) { 
    if( initCanvas ){
      g.setColor(Color.white);
      g.fillRect(0,0,dX,dY);
      parent.detector.draw(g);
      initCanvas=false;
    }
    ball.draw(g);
  } 
/*--------------------------------------------------*/ 
  public void setnDrops(int n) { 
    nDrops = n;
  }
/*--------------------------------------------------*/ 
  public void setGrav(double g) { 
    gPhysical = g;
  }
/*--------------------------------------------------*/ 
  public void setElevation(double ht) { 
    physicalHeight = ht;
  }
/*--------------------------------------------------*/ 
  public void setSpeedUp(double s) { 
    speedUp = s;
  }
}