package de.craften.plugins.rpgplus.components.entitymanager;

import de.craften.plugins.managedentities.ManagedEntityBase;
import de.craften.plugins.managedentities.behavior.SecondNameBehavior;
import de.craften.plugins.managedentities.behavior.VisibleNameBehavior;
import de.craften.plugins.managedentities.util.nms.NmsEntityUtil;
import org.bukkit.Location;
import org.bukkit.entity.*;

/**
 * A basic managed entity without any special logic.
 */
public abstract class RpgPlusEntity<T extends Entity> extends ManagedEntityBase<T> {
    private boolean isTakingDamage = true;
    private boolean nameVisible = true;

    public RpgPlusEntity(Location location) {
        super(location);

        addBehavior(new VisibleNameBehavior());
        addBehavior(new SecondNameBehavior());
    }

    @Override
    public void spawn() {
        super.spawn();

        if (getEntity() instanceof LivingEntity && !isTakingDamage) {
            NmsEntityUtil.setInvulnerable((LivingEntity) getEntity(), true);
        }
    }

    public String getName() {
        return getProperty(VisibleNameBehavior.NAME_PROPERTY_KEY);
    }

    public void setName(String name) {
        setProperty(VisibleNameBehavior.NAME_PROPERTY_KEY, name);
    }

    public String getSecondName() {
        return getProperty(SecondNameBehavior.NAME_PROPERTY_KEY);
    }

    public void setSecondName(String secondName) {
        setProperty(SecondNameBehavior.NAME_PROPERTY_KEY, secondName);
    }

    public boolean isTakingDamage() {
        return isTakingDamage;
    }

    public void setTakingDamage(boolean isTakingDamage) {
        this.isTakingDamage = isTakingDamage;

        if (getEntity() instanceof LivingEntity) {
            NmsEntityUtil.setInvulnerable((LivingEntity) getEntity(), !isTakingDamage);
        }
    }

    public boolean isNameVisible() {
        return nameVisible;
    }

    public void setNameVisible(boolean nameVisible) {
        if (nameVisible != this.nameVisible) {
            this.nameVisible = nameVisible;
            if (nameVisible) {
                removeBehavior(getBehaviors(VisibleNameBehavior.class).iterator().next());
            } else {
                addBehavior(new VisibleNameBehavior());
            }
        }
    }

    public Object getTarget() {
        Entity entity = getEntity();
        if (entity instanceof Creature) {
            return ((Creature) entity).getTarget();
        }
        return null;
    }

    public void setTarget(Player player) {
        Entity entity = getEntity();
        if (entity instanceof Creature) {
            ((Monster) entity).setTarget(player);
        }
        //TODO remember the target if the entity is not spawned yet
    }

    @Override
    public void teleport(Location location) {
        Location old = getLocation();
        if (old != null) {
            Location target = location.clone().setDirection(location.toVector().subtract(old.toVector()));
            super.teleport(target);
            
            if (getEntity() instanceof LivingEntity) {
                NmsEntityUtil.setHeadRotation((LivingEntity) getEntity(), target.getYaw(), target.getPitch());
            }
        } else {
            super.teleport(location);
        }
    }
}

@@ -378,17 +378,96 @@
 .entity.
-*
+Creature;%0Aimport org.bukkit.entity.Entity;%0Aimport org.bukkit.entity.LivingEntity
 ;%0A%0A/**%0A 
@@ -2339,21 +2339,235 @@
     
-public Object
+/**%0A     * Gets the target of this entity. This only works if the underlying entity is a %7B@link LivingEntity%7D.%0A     *%0A     * @return the target of this entity or null if this entity has no target%0A     */%0A    public LivingEntity
  get
@@ -2738,32 +2738,205 @@
 rn null;%0A    %7D%0A%0A
+    /**%0A     * Sets the target of this entity. This only works if the underlying entity is a %7B@link LivingEntity%7D.%0A     *%0A     * @param target target of this entity%0A     */%0A
     public void 
@@ -2949,21 +2949,27 @@
 get(
-Player player
+LivingEntity target
 ) %7B%0A
@@ -3065,15 +3065,16 @@
   ((
-Monster
+Creature
 ) en
@@ -3093,14 +3093,14 @@
 get(
-player
+target
 );%0A 
@@ -3451,28 +3451,16 @@
 arget);%0A
-            
 %0A       

Fix potential class cast exception when setting an entity's target and add javadoc.