// Player


class Player extends PhysicsObject {
  // Constants
  float frictionGround = 0.8;
  float movementSpeedGround = 1;
  // References
  Body bodyIAmOn; // if I'm on the ground, the body of whatever thing I'm on
  // Properties
  boolean isOnGround = true;
  boolean isMovementLocked = true;
  int direction = 1; // direction I'm facing -1 or 1 (left or right)
  float angle;
  //float xVel,yVel;
  float naturalW = 80;
  float naturalH = 120;
  float waddleOscillation=0;
  float waddleScale=0;
  float gravity = GRAVITY_DEFAULT;
  float friction = 0.8;
  // Components
  Body feet;
  SpeechBubble speechBubble;
  
  Player() {
    x = 0;
    y = 0;
    w = naturalW;
    h = naturalH;
    speechBubble = new SpeechBubble(this);
    speechBubble.textColor = color(128,255,80);
    makeBodyRect(new Vec2(x/WS,y/WS), w,h);
    makeFeet(x,y, w,h);
  }
  // This function adds the feet rectangle to the box2d world
  void makeFeet(float x,float y, float w_,float h_) {
    // Define a polygon (this is what we use for a rectangle)
    PolygonDef sd = new PolygonDef();
    float box2dW = box2d.scalarPixelsToWorld((w_-10)/2)/WS; // long
    float box2dH = box2d.scalarPixelsToWorld(5)/WS; // flat
    sd.setAsBox(box2dW, box2dH);
    // Parameters that affect physics
    sd.density = 1.0f;
    sd.friction = 0.0f; //friction will be done manually in my code
    sd.restitution = 0.0f;
    sd.isSensor = true;
    // Filter-- do NOT interact with other Aces
    sd.filter.categoryBits = 0x0002;
    sd.filter.maskBits = 0x0002;
    // Define the body and make it from the shape
    BodyDef bd = new BodyDef();
    bd.position.set(box2d.coordPixelsToWorld(new Vec2(x,y+h_/2)));
    feet = box2d.createBody(bd);
    feet.createShape(sd);
    feet.setMassFromShapes();
    feet.setLinearDamping(0.0f);
    // No initial velocity
    feet.setLinearVelocity(new Vec2(0, 0));
    feet.setAngularVelocity(0);
    //Stay awake!
    feet.allowSleeping(false);
  }
  
  
  void update() {
    // Math!
    getBodyInfo();
    applyGravity();
    groundDetection();
    groundFriction();
    controlMath();
    visualMath();
    // Speech bubba!
    speechBubble.update();
  }
  void draw() {
    // Speech bubba!
    speechBubble.draw();
    // Me!
    pushMatrix();
    translate(x,y);
    rotate(sin(waddleOscillation)*waddleScale);
    scale(direction, 1);
    drawBody();
    popMatrix();
  }
  void drawBody() {
//    fill(42,255,255);
//    stroke(42,255,200);
//    strokeWeight(2);
//    rect(0,0, w,h);
    image(playerBody_img, -w*0.5,-h*0.5, w,h);
  }
  
  
  void getBodyInfo() {
    setPos();

    //body.setAngularVelocity(0); //don't let me have any angleVel
    angle = body.getAngle(); //get its angle of rotation
    //limit angle
    if (angle<-0.1) angle = -0.1;
    if (angle>0.1) angle = 0.1;
    if (!isOnGround) angle = 0;
    body.setXForm(box2d.coordPixelsToWorld(new Vec2(x/WS, y/WS)), angle);
    feet.setXForm(box2d.coordPixelsToWorld(new Vec2(x/WS, (y+h/2)/WS)), angle*0); // SEMI-HACK - not accurate placement (doesn't account for angle)
  }
  void setPos() {
    Vec2 pos = box2d.getBodyPixelCoord(body); //get its screen position
    x = pos.x * WS;
    y = pos.y * WS;
  }
  
  void applyGravity() {
    body.setLinearVelocity(new Vec2(body.getLinearVelocity().x, body.getLinearVelocity().y-gravity));
  }
  void groundDetection() {
    isOnGround = false; // We'll say otherwise shortly.
    bodyIAmOn = null; // We'll say otherwise shortly.
    // go through list of things my feet are touching; if it's something I can stand on, consider onGround to be true.
    ContactEdge edge = feet.getContactList();
    while (edge!=null) {
      if (edge.other.getUserData()=="boundary") {
        isOnGround = true;
        bodyIAmOn = edge.other; // set bodyIAmOn
      }
      edge = edge.next;
    }
  }
  void groundFriction() {
    if (isOnGround) body.setLinearVelocity(new Vec2(body.getLinearVelocity().x*friction, body.getLinearVelocity().y));
  }
  
  
  void controlMath() {
    if (!canControlPlayer()) return;
    float movementSpeed = 0;
    if (isOnGround) movementSpeed = movementSpeedGround;
    //else movementSpeed = movementSpeedAir;
    
    if (keyDown_LEFT) {
      body.setLinearVelocity(new Vec2(body.getLinearVelocity().x-movementSpeed, body.getLinearVelocity().y));
      direction = -1;
    }
    if (keyDown_RIGHT) {
      body.setLinearVelocity(new Vec2(body.getLinearVelocity().x+movementSpeed, body.getLinearVelocity().y));
      direction = 1;
    }
  }
  void visualMath() {
    // waddling!
    waddleOscillation += body.getLinearVelocity().x*0.16;
    waddleScale = abs(body.getLinearVelocity().x)*0.04;
  }
  
  void speak(String speechText) {
    float X = x + 50;
    float Y = y-h - 100;
    speechBubble.appear(X,Y, speechText);
  }
  
  
  
  // This function removes the particle from the box2d world
  void killBody() {
    super.killBody();
    if (feet != null) {
      box2d.destroyBody(feet);
      feet = null;
    }
  }
  
  
  
}
