// TimerWorld.java

import java.util.Random;


// ------------------------------------------------------------------------------
// represent the world of a Blob
class TimerWorld extends World {

   int width = 200;
   int height = 400;
   Blob blob;

   TimerWorld(Blob blob) {
     this.blob = blob;
   }

   // what happens when the player presses a key
   World onKeyEvent(String ke) {
     return new TimerWorld(this.blob.moveBlob(ke));
   }

   // what happens when the clock ticks
   World onTick() {
     // if the blob is outside the canvas, stop
     if (this.blob.outsideBounds(this.width, this.height)
        && this.stop())
     	return this;

     // else move the blob randomly at most 5 pixels in any direction
     else
       return new TimerWorld(this.blob.randomMove(5));
   }

   // draw this world
   public boolean draw() {
     return this.drawRect(new Posn(0, 0), this.width, this.height, new Blue())
         && this.blob.draw(this);
   }

}


/*
;                                 
;                                 
;                                 
;   ;;;;;  ;           ;          
;   ;    ; ;           ;          
;   ;    ; ;           ;          
;   ;   ;  ;    ;;;    ; ;;       
;   ;;;;   ;   ;   ;   ;;  ;      
;   ;   ;  ;  ;     ;  ;    ;     
;   ;    ; ;  ;     ;  ;    ;     
;   ;    ; ;  ;     ;  ;    ;     
;   ;    ; ;   ;   ;   ;;  ;      
;   ;;;;;  ;    ;;;    ; ;;       
;                                 
;                                 
;                                 
*/
// to represent a blob on the canvas
class Blob {
  Posn center;
  int radius;

  Blob(Posn center, int radius) {
    this.center = center;
    this.radius = radius;
  }

  // draw this blob in the given World
  boolean draw(World w) {
    return w.drawDisk(this.center, this.radius, new Red());
  } 

  // move this blob 20 pixels in the direction given by the ke
  Blob moveBlob(String ke){
    if (ke.equals("right"))
       return new Blob(new Posn(this.center.x + 20, this.center.y), 
                         this.radius);
    else if (ke.equals("left"))
       return new Blob(new Posn(this.center.x - 20, this.center.y), 
                         this.radius);
    else if (ke.equals("up"))
       return new Blob(new Posn(this.center.x, this.center.y - 20), 
                         this.radius);
    else if (ke.equals("down"))
       return new Blob(new Posn(this.center.x, this.center.y + 20), 
                         this.radius);
    else
       return this;
  }

  // produce a new blob moved by a random distance < n pixels
  Blob randomMove(int n){
    return new Blob(new Posn(this.center.x + this.randomInt(n),
                             this.center.y + this.randomInt(n) ),
                      this.radius);
  }

  // helper method to generate a random number in the range -n to n
  int randomInt(int n){
    return -n + (new Random().nextInt()) % (2 * n);
  }

  // is the blob outside the bounds given by the width and height
  boolean outsideBounds(int width, int height) {
	return this.center.x < 0
            || this.center.x > width
	    || this.center.y < 0 
            || this.center.y > height;
  }

  // determine whether this blob is the same as than given blob
  boolean same(Blob b){
    return this.center.x == b.center.x
        && this.center.y == b.center.y
        && this.radius == b.radius;
  }
 
  
  // run the tests and start the world
  public static void main(String[] argv){

    // Tests for the Blob class:
    Blob b1 = new Blob(new Posn(100, 100), 50);
    Blob b2 = b1.moveBlob("left");

    System.out.println(
		"test moveBolb - left " + "\n" +
  		(b1.moveBlob("left").same(new Blob(new Posn(80, 100), 50))) + "\n" +
  		"test movelob - right " + "\n" +
		(b1.moveBlob("right").same(new Blob(new Posn(120, 100), 50))) + "\n" +
		"test moveBlob - up " + "\n" +
		(b1.moveBlob("up").same(new Blob(new Posn(100, 80), 50))) + "\n" +
		"test moveBlob - down " + "\n" +
		(b1.moveBlob("down").same(new Blob(new Posn(100, 120), 50))) + "\n" +
		
		"test testOutsideBounds " + "\n" +
		(b1.outsideBounds(60, 200) == true) + "\n" +
         (b1.outsideBounds(100, 90) == true) + "\n" +
         (new Blob(new Posn(-5, 100), 50).outsideBounds(100, 110) == true) + "\n" +
         (new Blob(new Posn(80, -5), 50).outsideBounds(100, 90) == true) + "\n" +
         (b1.outsideBounds(200, 400) == false) + "\n" +

		"test randomInt " + "\n" +
		(b1.randomInt(5) <= 5 && b1.randomInt(5) >= -5) + "\n" +
		
		"test randomMove " + "\n" +
		(b1.randomMove(5).center.x <= 105 &&
         b1.randomMove(5).center.x >= 95 &&
         b1.randomMove(5).center.y <= 105 &&
         b1.randomMove(5).center.y >= 95) + "\n"

		);

    		// construct an instance of a TimerWorld
    		TimerWorld w = new TimerWorld(new Blob(new Posn(100, 200), 20));
 
    		// start the world, start the timer and key event monitoring
		boolean testWorld = w.start(200,400) 
                          && w.theWorld.bigBang(0.3, w, true, false);

  }

}

