package de.gurkenlabs.litiengine.entities;

import java.awt.geom.Point2D;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;

import de.gurkenlabs.litiengine.Game;
import de.gurkenlabs.litiengine.annotation.AnimationInfo;
import de.gurkenlabs.litiengine.annotation.MovementInfo;
import de.gurkenlabs.util.geom.GeometricUtilities;

@MovementInfo
public class Creature extends CombatEntity implements IMobileEntity {
  private static final int IDLE_DELAY = 100;
  private int acceleration;
  private int deceleration;
  private final List<Consumer<IMobileEntity>> entityMovedConsumer;
  /** The last moved. */
  private long lastMoved;

  private Point2D moveDestination;
  private boolean turnOnMove;

  private short velocity;

  private String spritePrefix;

  public Creature() {
    super();
    this.entityMovedConsumer = new CopyOnWriteArrayList<>();
    final MovementInfo info = this.getClass().getAnnotation(MovementInfo.class);
    this.velocity = info.velocity();
    this.acceleration = info.acceleration();
    this.deceleration = info.deceleration();
    this.setTurnOnMove(info.turnOnMove());

    AnimationInfo animationInfo = this.getClass().getAnnotation(AnimationInfo.class);
    if (animationInfo != null) {
      this.setSpritePrefix(animationInfo.spritePrefix());
    } else {
      this.setSpritePrefix(this.getClass().getSimpleName().toLowerCase());
    }
  }

  @Override
  public int getAcceleration() {
    return this.acceleration;
  }

  @Override
  public int getDeceleration() {
    return this.deceleration;
  }

  public Direction getFacingDirection() {
    return Direction.fromAngle(this.getAngle());
  }

  @Override
  public Point2D getMoveDestination() {
    return this.moveDestination;
  }

  public String getSpritePrefix() {
    return spritePrefix;
  }

  @Override
  public float getVelocity() {
    return this.velocity * this.getAttributes().getVelocity().getCurrentValue();
  }

  /**
   * Checks if is idle.
   *
   * @return true, if is idle
   */
  public boolean isIdle() {
    return Game.getLoop().getDeltaTime(this.lastMoved) > IDLE_DELAY;
  }

  @Override
  public void onMoved(final Consumer<IMobileEntity> consumer) {
    if (this.entityMovedConsumer.contains(consumer)) {
      return;
    }

    this.entityMovedConsumer.add(consumer);
  }

  @Override
  public void setAcceleration(final int acceleration) {
    this.acceleration = acceleration;
  }

  @Override
  public void setDeceleration(final int deceleration) {
    this.deceleration = deceleration;
  }

  public void setFacingDirection(final Direction facingDirection) {
    this.setAngle(Direction.toAngle(facingDirection));
  }

  @Override
  public void setLocation(final Point2D position) {
    if (this.isDead() || position == null || GeometricUtilities.equals(position, this.getLocation(), 0.001)) {
      return;
    }

    super.setLocation(position);

    if (Game.hasStarted()) {
      this.lastMoved = Game.getLoop().getTicks();
    }

    for (final Consumer<IMobileEntity> consumer : this.entityMovedConsumer) {
      consumer.accept(this);
    }
  }

  @Override
  public void setMoveDestination(final Point2D dest) {
    this.moveDestination = dest;
    this.setAngle((float) GeometricUtilities.calcRotationAngleInDegrees(this.getLocation(), this.getMoveDestination()));
  }

  @Override
  public void setTurnOnMove(final boolean turn) {
    this.turnOnMove = turn;
  }

  @Override
  public void setVelocity(final short velocity) {
    this.velocity = velocity;
  }

  public void setSpritePrefix(String spritePrefix) {
    this.spritePrefix = spritePrefix;
  }

  @Override
  public boolean turnOnMove() {
    return this.turnOnMove;
  }
}
@@ -866,22 +866,8 @@
  %7B%0D%0A
-    super();%0D%0A
     
@@ -947,17 +947,25 @@
 entInfo 
-i
+movementI
 nfo = th
@@ -1010,24 +1010,59 @@
 fo.class);%0D%0A
+    if (movementInfo != null) %7B%0D%0A  
     this.vel
@@ -1069,17 +1069,25 @@
 ocity = 
-i
+movementI
 nfo.velo
@@ -1095,24 +1095,26 @@
 ity();%0D%0A    
+ 
+ 
 this.acceler
@@ -1117,25 +1117,33 @@
 eleration = 
-i
+movementI
 nfo.accelera
@@ -1151,24 +1151,26 @@
 ion();%0D%0A    
+  
 this.deceler
@@ -1177,17 +1177,25 @@
 ation = 
-i
+movementI
 nfo.dece
@@ -1203,24 +1203,26 @@
 eration();%0D%0A
+  
     this.set
@@ -1232,17 +1232,25 @@
 nOnMove(
-i
+movementI
 nfo.turn
@@ -1260,16 +1260,23 @@
 ove());%0D
+%0A    %7D%0D
 %0A%0D%0A    A
@@ -1536,24 +1536,24 @@
 erCase());%0D%0A
-
     %7D%0D%0A  %7D%0D%0A
@@ -1546,32 +1546,135 @@
 %0D%0A    %7D%0D%0A  %7D%0D%0A%0D%0A
+  public Creature(String spritePrefix) %7B%0D%0A    this();%0D%0A    this.setSpritePrefix(spritePrefix);%0D%0A  %7D%0D%0A%0D%0A
   @Override%0D%0A  p

Add constructor overload.