package entities;

import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

import snake.Screen;

public class Snake extends Entity {
  public static final int SIZE = 20;
  protected static final int BORDER = 1;

  private double x;
  private double y;

  public int prevCellX;
  public int prevCellY;

  private double speed = 1.0;

  private double xVel = speed;
  private double yVel = 0.0;

  public List<BodyPiece> body;

  public int score;

  private boolean dead = false;

  public Snake() {
    this.x = 100;
    this.y = 100;
    this.cellX = (int) this.x;
    this.cellY = (int) this.y;
    this.prevCellX = this.cellX;
    this.prevCellY = this.cellY;
    body = new ArrayList<BodyPiece>(0);
    this.score = 0;
  }

  @Override
  public void draw(Graphics2D g2d) {
    g2d.fillRect(
        cellX + BORDER,
        cellY + BORDER,
        SIZE - 2 * BORDER,
        SIZE - 2 * BORDER);
    for (BodyPiece bp : body) {
      bp.draw(g2d);
    }
  }

  @Override
  public void update(boolean[] keys) {
    prevCellX = cellX;
    prevCellY = cellY;

    if (keys[KeyEvent.VK_RIGHT] && xVel != -speed) {
      xVel = speed;
      yVel = 0;
    }
    if (keys[KeyEvent.VK_LEFT] && xVel != speed) {
      xVel = -speed;
      yVel = 0;
    }
    if (keys[KeyEvent.VK_UP] && yVel != speed) {
      xVel = 0;
      yVel = -speed;
    }
    if (keys[KeyEvent.VK_DOWN] && yVel != -speed) {
      xVel = 0;
      yVel = speed;
    }

    x += xVel;
    y += yVel;
    cellX = (int) (x / SIZE) * SIZE;
    cellY = (int) (y / SIZE) * SIZE;

    if (cellX != prevCellX || cellY != prevCellY) {
      // This has to be done because for most ticks the previous cellX is the same as the current cellX
      // because we're moving at 'subpixels'
      if (body.size() > 0) {
        body.get(0).move(prevCellX, prevCellY);
      }
      for (int i = 0; i < body.size() - 1; i++) {
        // 0 is the first body part
        // however it has a pos of 1
        body.get(i + 1).move(body.get(i).prevCellX, body.get(i).prevCellY);
      }
      if (collide(Screen.walls) || selfCollide(body)) {
        dead = true;
      }
    }
  }

  public void eat(Food food) {
    if (collide(food)) {
      ++this.score;
      food.update();
      speed += speed * 0.05;
      if (body.size() < 1)
        body.add(new BodyPiece(prevCellX, prevCellY));
      else
        body.add(new BodyPiece(body.get(body.size() - 1).prevCellX, body.get(body.size() - 1).prevCellY));
    }
  }

  // Custom collide that calls collide on each Entity
  public boolean selfCollide(List<BodyPiece> body) {
    boolean hit = false;
    for (BodyPiece e : body) {
      hit |= super.collide(e);
    }
    return hit;
  }

  public boolean isDead() {
    return dead;
  }
}

@@ -443,16 +443,116 @@
 = 0.0;%0A%0A
+  private enum D %7B%0A    UP, RIGHT, DOWN, LEFT%0A  %7D;%0A%0A  private D dir = D.RIGHT;%0A  private D prevDir;%0A%0A
   public
@@ -812,24 +812,29 @@
 .cellY;%0A    
+this.
 body = new A
@@ -1248,455 +1248,226 @@
 GHT%5D
- && xVel != -speed) %7B%0A      xVel = speed;%0A      yVel = 0;%0A    %7D%0A    if (keys%5BKeyEvent.VK_LEFT%5D && xVel != speed) %7B%0A      xVel = -speed;%0A      yVel = 0;%0A    %7D%0A    if (keys%5BKeyEvent.VK_UP%5D && yVel != speed) %7B%0A      xVel = 0;%0A      yVel = -speed;%0A    %7D%0A    if (keys%5BKeyEvent.VK_DOWN%5D && yVel != -speed) %7B%0A      xVel = 0;%0A      yVel = speed;%0A    %7D%0A%0A    x += xVel;%0A    y += yVel;%0A    cellX = (int) (x / SIZE) * SIZE;%0A    cellY = (int) (y / SIZE) * SIZE
+) %7B%0A      dir = D.RIGHT;%0A    %7D%0A    if (keys%5BKeyEvent.VK_LEFT%5D) %7B%0A      dir = D.LEFT;%0A    %7D%0A    if (keys%5BKeyEvent.VK_UP%5D) %7B%0A      dir = D.UP;%0A    %7D%0A    if (keys%5BKeyEvent.VK_DOWN%5D) %7B%0A      dir = D.DOWN;%0A    %7D%0A%0A    move()
 ;%0A%0A 
@@ -2391,16 +2391,718 @@
  %7D%0A  %7D%0A%0A
+  public void move() %7B%0A    if ((dir == D.RIGHT && prevDir == D.LEFT) %7C%7C%0A        (dir == D.LEFT && prevDir == D.RIGHT) %7C%7C%0A        (dir == D.UP && prevDir == D.DOWN) %7C%7C%0A        (dir == D.DOWN && prevDir == D.UP)) %7B%0A      dir = prevDir;%0A    %7D else %7B%0A      switch (dir) %7B%0A      case UP:%0A        xVel = 0;%0A        yVel = -speed;%0A        break;%0A      case RIGHT:%0A        xVel = speed;%0A        yVel = 0;%0A        break;%0A      case DOWN:%0A        xVel = 0;%0A        yVel = speed;%0A        break;%0A      case LEFT:%0A        xVel = -speed;%0A        yVel = 0;%0A        break;%0A      %7D%0A      prevDir = dir;%0A    %7D%0A%0A    x += xVel;%0A    y += yVel;%0A    cellX = (int) (x / SIZE) * SIZE;%0A    cellY = (int) (y / SIZE) * SIZE;%0A  %7D%0A%0A
   // Cus

Change snake dir to use enums