import pphys2d.bodies.*;
import pphys2d.joints.*;
import pphys2d.shapes.*;
import pphys2d.phys2d.raw.collide.*;
import pphys2d.phys2d.raw.strategies.*;
import pphys2d.phys2d.raw.forcesource.*;
import pphys2d.phys2d.util.*;
import pphys2d.phys2d.raw.shapes.*;
import pphys2d.*;
import pphys2d.phys2d.raw.*;
import pphys2d.phys2d.math.*;

int PREGAME = 0;
int GAME = 1;
int POSTGAME = 2;
int gamemode = PREGAME;

HashSet particles = new HashSet();

PPWorld world;

void setup(){
  size(500,500);
  rectMode(CENTER);
  textFont(createFont("",24),24);

  world  = new PPWorld();
}
void draw(){
  background(0);
  if(gamemode == PREGAME) {
    drawPregame();
    if(isKeyDown(32)){
      resetGame();
      gamemode = GAME; 
    }
  }
  if(gamemode == POSTGAME){
    drawPostgame();
  }
  if(gamemode == GAME){
    controlRocket();
    drawChecks();

    world.draw(this);
    checkPos();
    drawTimes();

    

    Iterator i = particles.iterator();
    while(i.hasNext()){
      Particle p = (Particle)i.next(); 
      p.move();
      p.draw();
      if(p.isDead()){
        i.remove();
      }  
    }

  }

  if(mousePressed){
    mouseDragged(); 
  }
}
float startLap;
Float bestLap = null;
Float lastLap = null;

void drawTimes(){
  fill(0);
  rectMode(CORNER);
  float time = (millis() - startLap)/1000;
  textAlign(LEFT);

  text("time:"+time,200,280);

  if(lastLap != null) text("last:"+lastLap,200,300);
  if(bestLap != null) text("best:"+bestLap,200,320);


}

int START = 0;
int LINE1 = 1;
int LINE2 = 2;
int lasthit = START; 

String lastmsg = "";


void checkPos(){
  float x = rocket.getX();
  float y = rocket.getY();
  if(x >= 210 && x <= 210+20 && y >=150 && y <= 150+80){
    if(lasthit == START){
      lasthit = LINE1; 
    }
  }
  if(x >= 0 && x <=40 && y >=200 && y <= 220){
    if(lasthit == LINE1){
      lasthit = LINE2; 
    } 
  }
  if(x >= 180 && x <=180+80 && y >=395){
    if(lasthit == LINE2){
      lasthit = START; 
      lastLap = (millis() - startLap)/1000;
      if(bestLap == null || lastLap < bestLap){
        bestLap = lastLap; 
      }
      startLap = millis();
    } 
  }

}

void drawChecks(){
  rectMode(CORNER);
  fill(255);
  noStroke();
  float ssize = 20;
  for(int a = 0; a < 5; a++){
    for(int b = 0; b < 4; b++){
      fill(random(255));
      rect(180+(b*ssize),395+(a*ssize),ssize,ssize);    
    }
  }

  fill(random(128));
  rect(210,150,20,80);

  fill(random(128));
  rect(0,200,40,20);

}


PPConvexPoly rocket; 
void resetGame(){ 
  startLap = millis();
  ;
  world.setGravity(0,0);
  world.setEdges(this, new Color (255, 200, 40));
  rocket = new PPConvexPoly();
  rocket.vertex(0, -5);
  rocket.vertex(4,8);
  rocket.vertex(-4,8);
  rocket.setFillColor(new Color(200,30,30));
  rocket.setStrokeColor(new Color(128,128,128));
  rocket.setPosition(250,450);
  rocket.setRestitution(.5);
  rocket.setRotation(PI/2);

  world.add(rocket);


  addRock(213.0,311.0,104.0,170.0);
  addRock(280.5,302.5,95.0,89.0);
  addRock(424.0,424.0,82.0,138.0);
  addRock(431.0,165.0,128.0,138.0);
  addRock(263.5,78.0,109.0,148.0);
  addRock(376.0,71.0,170.0,90.0);
  addRock(143.5,163.5,55.0,131.0);
  addRock(80.0,199.0,84.0,94.0);
  addRock(112.0,326.0,106.0,76.0);
  addRock(41.0,459.5,70.0,77.0);

}

Color rockColor =  new Color (255, 200, 40);

float startX,startY;
void mousePressed(){
  startX = mouseX; 
  startY = mouseY; 
}
void mouseDragged(){
  stroke(255);
  noFill();
  float midX = (mouseX+startX)/2;
  float midY = (mouseY+startY)/2;
  float w = abs(mouseX - startX);
  float h = abs(mouseY - startY);

  rect(midX,midY,w,h);
}
void mouseReleased(){
  float midX = (mouseX+startX)/2;
  float midY = (mouseY+startY)/2;
  float w = abs(mouseX - startX);
  float h = abs(mouseY - startY);
  addRock(midX,midY,w,h);
  // println("addRock("+midX+","+midY+","+w+","+h+")");
}

void addRock(float x, float y, float w, float h){
  PPBox rock = new PPBox(w,h);
  rock.setPosition(x,y);
  rock.setFillColor(rockColor);
  rock.setStaticBody(true);
  rock.setRestitution(.5);
  world.add(rock);
}

float ROT = .2;
float MAXROT = 3;

class Particle{
  float x = rocket.getX();
  float y = rocket.getY();
  float xs;// = rocket.getVelocityX()/100;
  float ys;// = rocket.getVelocityY()/100;
Particle(int dir){
  /*float OFFSET =0;
  if(dir == UP) OFFSET = +PI/2.0;
  if(dir == LEFT) OFFSET = +PI/4.0;
  if(dir == UP) OFFSET = -PI/4.0;*/
     float rotation = rocket.getRotation() + PI/2;//OFFSET;
      ys = sin(rotation)+ (rocket.getVelocityY()/100);
      xs = cos(rotation)+ (rocket.getVelocityX()/100);
}  

  int health = 500;
  void move(){
    health --;
    x += xs;
    y += ys;
  }
  void draw(){
    noStroke();
    stroke(random(128,255),0,0);
    rect(x,y,1,1);

  }
  boolean isDead(){
    return health < 0; 
  }
}
void controlRocket(){
  if(isKeyDown(37)){//left{
    rocket.adjustAngularVelocity(-ROT);
    
  }
  if(isKeyDown(39)){//right
    rocket.adjustAngularVelocity(ROT);
    
  }
  if(isKeyDown(38) || isKeyDown(32)){//up
    float rotation = rocket.getRotation()-PI/2.0;
    float force = 40000.0f;
    rocket.addForce(cos(rotation)*force, sin(rotation)*force);   
    
    if(frameCount % 3 == 0){
       particles.add(new Particle(UP)); 
    }

  }

  if(rocket.getAngularVelocity() > MAXROT){
    rocket.setAngularVelocity(MAXROT); 
  }

  if(rocket.getAngularVelocity() < -MAXROT){
    rocket.setAngularVelocity(-MAXROT); 
  }


}


void drawPregame(){
  //  pushMatrix();
  //  translate(width/3,height/3);
  rectMode(CORNER);
  fill(255);
  textAlign(CENTER);
  text("ROTATIN' ROCKET RACE\n\nhow fast can you go around the track?\n\narrows turn, space thrusts\n\nspace to start\n\n",50,100,400,350);
  //  popMatrix();
}
void drawPostgame(){

}

HashSet keysDown = new HashSet();
void keyPressed(){
  //println(this.keyEvent.getKeyCode());
  this.keysDown.add(this.keyEvent.getKeyCode());
}
void keyReleased(){
  this.keysDown.remove(this.keyEvent.getKeyCode());  
}
boolean isKeyDown(int keyCode){
  if(keysDown.contains(keyCode)) return true;
  return false; 
}