package eu.mhsl.minenet.minigames.shared.entity;

import eu.mhsl.minenet.minigames.instance.Spawnable;
import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.EntityType;
import net.minestom.server.event.entity.EntityAttackEvent;
import net.minestom.server.event.instance.AddEntityToInstanceEvent;
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
import net.minestom.server.event.player.PlayerEntityInteractEvent;
import net.minestom.server.event.player.PlayerMoveEvent;
import org.jetbrains.annotations.NotNull;


public class InteractableEntity extends EntityCreature {

    /**
     * Declares an Entity with direct callbacks on interaction
     * @param entityType type of entity
     */
    public InteractableEntity(@NotNull EntityType entityType) {
        super(entityType);

        eventNode()
                .addListener(AddEntityToInstanceEvent.class, this::setInstanceEvent)

                .addListener(AddEntityToInstanceEvent.class, this::onSpawn)
                .addListener(RemoveEntityFromInstanceEvent.class, this::onDespawn)
                .addListener(PlayerEntityInteractEvent.class, this::onInteract) //TODO Why are some of these listeners not working?

                .addListener(EntityAttackEvent.class, this::onAttack);
    }

    private void setInstanceEvent(@NotNull AddEntityToInstanceEvent addEntityToInstanceEvent) {
        if(addEntityToInstanceEvent.getInstance() instanceof Spawnable instance) {
            scheduleNextTick((unused) -> this.teleport(this.position.withPitch(180).withYaw(0)));
        }

        addEntityToInstanceEvent.getInstance().eventNode()
                .addListener(PlayerMoveEvent.class, playerMoveEvent -> {
                    //TODO might be expensive
                    if(this.position.distance(playerMoveEvent.getNewPosition()) < 5)
                        this.lookAt(playerMoveEvent.getPlayer());
                })
                .addListener(PlayerEntityInteractEvent.class, playerEntityInteractEvent -> {
                    if(playerEntityInteractEvent.getTarget() == this) {
                        onInteract(playerEntityInteractEvent);
                    }
                })
                .addListener(EntityAttackEvent.class, entityAttackEvent -> {
                   if(entityAttackEvent.getTarget() == this) {
                       onAttack(entityAttackEvent);
                   }
                });
    }

    /**
     * Called when instance of entity is set
     * @param addEntityToInstanceEvent
     */
    protected void onSpawn(@NotNull AddEntityToInstanceEvent addEntityToInstanceEvent) {

    }

    /**
     * Called when instance of entity is unset
     * @param removeEntityFromInstanceEvent
     */
    protected void onDespawn(@NotNull RemoveEntityFromInstanceEvent removeEntityFromInstanceEvent) {

    }

    /**
     * Called when a Player interacts with the entity
     * @param playerEntityInteractEvent
     */
    protected void onInteract(@NotNull PlayerEntityInteractEvent playerEntityInteractEvent) {

    }

    /**
     * Called when a Player attacks the entity
     * @param entityAttackEvent
     */
    protected void onAttack(@NotNull EntityAttackEvent entityAttackEvent) {

    }
}
