import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

// Dilip Barman  November 22, 1997
// file AnimationObject.java

// 3rd java homework assignment to play with multimedia and double buffering.
// This is the class used by the main class, DilipsAnimationApplet


public class AnimationObject 
extends Thread    // Each object runs as a thread
  
{

  // ***********  Debug Variables   ***********
  static DebugWindow debugWindow = new DebugWindow("AnimationObject");
  private boolean debugMode = true;   // set to true to enable debug window msgs

  // can use statements like this in code:
  // if (debugMode) { debugWindow.print("Just created frame"); }

  // ***********  Constants   ***********
  // ***********  Class Variables   ***********

  // ***********  Instance Variables   ***********
  Graphics g;
  Dimension outareaSize;
  Applet parentApplet;   // passed in - what applet we're coming from
    
  int delay;
  static Random random = new Random();
  // static Image bikeImage = Toolkit.getDefaultToolkit().getImage
  //                          ("images/bikeFridayLogo3.gif");

  int xPos, yPos;                   // Object location
  long incr, xincr, yincr, theta;   // Movement increments and angle
  int boundaryLeft, boundaryRight, boundaryTop, boundaryBottom;   // output boundary box
  Color myColor;                    // Object color
  int myWidth;                      // Object width
  String myType;                    // Object type - circle, square


  // ***********  Constructor and Destructor Methods ***********

  //         AnimationObject ( Graphics graphicsContext, Dimension frameSize )
  //           {  super (); g = graphicsContext; outareaSize= frameSize; init ();   } 

  // Store graphics context, drawing dimensions, and parent applet
  AnimationObject ( Graphics graphicsContext, Dimension frameSize, Applet callingApplet )
  {
       super ();
       if (debugMode) 
         {  debugWindow.print("Entering constructor with parent Applet:");
            debugWindow.print ("  '" + callingApplet + "'");
         }
       g = graphicsContext;
       outareaSize= frameSize;
       parentApplet = callingApplet;
       init ();

       if (debugMode) { debugWindow.print("Exiting constructor"); }
   
  }  // end constructor


  // Destructor - to kill debug window if it exists; I couldn't figure out how to
  // make it a class method that I could call, so I must call it as a message to
  // an instance.  
  public void quit() 
  {
      if (debugMode) 
        { 
          debugWindow.print("About to quit"); 
          debugWindow.setVisible (false);
        }
  }
  //protected void finalize()
  //  {
  //    if (debugMode) 
  //      { 
  //        debugWindow.print("About to quit"); 
  //        debugWindow.setVisible (false);
  //      }
  //  }



  // ***********  run() Method for Thread ***********

  public void run () 
  {
       try
         {
          while ( true )
            {
	      // White(=background)-out old position, get new (x,y) coordinates,
	      // and draw object in its new position
               synchronized ( g )
                 {  g.setColor ( Color.white );  
                    if (myType == "circle")
                      { g.fillOval ( xPos, yPos, myWidth, myWidth ); }
                    else
                      { g.fillRect ( xPos, yPos, myWidth, myWidth ); }

                    moveObject ();   

                    g.setColor ( myColor );
                    if (myType == "circle")
                      { g.fillOval ( xPos, yPos, myWidth, myWidth ); }
                    else
                      { g.fillRect ( xPos, yPos, myWidth, myWidth ); }
                    // g.drawImage(bikeImage, xPos, yPos, parentApplet);
                 }  // end synchronized
               sleep ( delay );
            }  // end while
         }  // end try
       catch ( InterruptedException except) 
         {  System.out.println ( "Interrupt in AnimationObject" );
            return;
         }  // end catch
  }  // end run

 
  // ***********  Methods to Initialize and Delete Objects   ***********

  private void init () 
  {
      if (debugMode) 
        { debugWindow.print("Initializing object in init()"); }
   
      myWidth = 40;    // size of object; we'll use 80% for squares
      incr = 3;         
      delay = 15 - (int) (10 * random.nextFloat() );

      // Assign object type at random
      if (random.nextFloat() <= .5) { myType = "circle"; }
      else { myType = "square"; myWidth = 32; }

      boundaryLeft = 0;
      boundaryRight = outareaSize.width - myWidth;
      boundaryTop = 0;
      boundaryBottom = outareaSize.height - myWidth ;

      boolean test = true;
      while ( test ) 
        {
	  // Pick random (x,y) in bounds, subtracting space object occupies
           xPos = (int)( (outareaSize.width - myWidth) * random.nextFloat () );
           yPos = (int)( (outareaSize.height - myWidth) * random.nextFloat () );
           if ( ( xPos > 5 ) && ( yPos > 5 ) ) test = false;
        } 
      test = true;
      while ( test )
        {
	  theta = (long)( 360 * random.nextFloat () );   // choose rnd angle
	  xincr = (long)(incr * Math.cos ( theta ) );    // calc (x,y) displacements
	  yincr = (long)(incr * Math.sin ( theta ) );    //   in that direction
           if ( (Math.abs(xincr) > 1 ) &&  (Math.abs(yincr) > 1) ) test = false;
        }  // end while

      // Choose random color
      int colorR = (int)( 255 * random.nextFloat () );
      int colorG = (int)( 255 * random.nextFloat () );
      int colorB = (int)( 255 * random.nextFloat () );
      myColor = new Color ( colorR, colorG, colorB );

      if (debugMode) 
        { debugWindow.print("Done creating " + myType + " of width " + myWidth +
                            " at (" + xPos + "," + yPos + ") and angle " +
                            theta + "deg and of color R=" + colorR + " G=" + colorG +
                            " B=" + colorB + "."); }

  }  // end init

  public void delete ()  
  {
      if (debugMode) 
        { debugWindow.print("AnimationObject: deleting object in delete()"); }
      g.setColor ( Color.white );
      if (myType == "circle")
        { g.fillOval ( xPos, yPos, myWidth, myWidth ); }
      else   // square
        { g.fillRect (xPos, yPos, myWidth, myWidth); }
  }


  // ***********  Methods to Move Object an Increment   ***********

  private void moveObject ()
       // Move -- set xPos and yPos -- as per xincr and yincr increments; if
       // this would go past the boundary, "bounce" by reversing direction
  {
       if ( (int)(xPos + xincr) > boundaryRight || (int)(xPos + xincr) < boundaryLeft ) 
         { xincr = -1 * xincr; }
       else xPos = (int)(xPos + xincr);

       if ( (int)(yPos + yincr) > boundaryBottom || (int)(yPos + yincr) < boundaryTop )
         { yincr = -1 * yincr; }
       else yPos = (int)(yPos + yincr);

  } 

}  // end AnimationObject class definition



