package net.miarma.hystuff.events;

import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.system.RefChangeSystem;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.Universe;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import net.miarma.hystuff.common.LastPositionManager;
import net.miarma.hystuff.common.Location;
import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

import java.util.UUID;

public class PlayerDeathListener extends RefChangeSystem<EntityStore, DeathComponent> {
    private final LastPositionManager lastPositionManager;
    private final HytaleLogger LOGGER;

    public PlayerDeathListener(LastPositionManager lastPositionManager, HytaleLogger logger) {
        this.lastPositionManager = lastPositionManager;
        this.LOGGER = logger;
    }

    @NonNullDecl
    @Override
    public ComponentType<EntityStore, DeathComponent> componentType() {
        return DeathComponent.getComponentType();
    }

    @Override
    public void onComponentAdded(@NonNullDecl Ref<EntityStore> ref,
                                 @NonNullDecl DeathComponent deathComponent,
                                 @NonNullDecl Store<EntityStore> store,
                                 @NonNullDecl CommandBuffer<EntityStore> commandBuffer) {
        try {
            Universe universe = Universe.get();
            if (universe == null) {
                return;
            }

            ComponentType<EntityStore, PlayerRef> playerRefType = universe.getPlayerRefComponentType();
            if (playerRefType == null) {
                return;
            }

            PlayerRef playerRef = store.getComponent(ref, playerRefType);
            if (playerRef == null) {
                return;
            }

            UUID playerUuid = playerRef.getUuid();
            TransformComponent transform = store.getComponent(ref, TransformComponent.getComponentType());
            if (transform == null) {
                return;
            }

            Vector3d pos = transform.getPosition();
            HeadRotation headRotation = store.getComponent(ref, HeadRotation.getComponentType());
            float yaw = 0.0f;
            float pitch = 0.0f;
            if (headRotation != null) {
                Vector3f rotation = headRotation.getRotation();
                yaw = rotation.getYaw();
                pitch = rotation.getPitch();
            }

            String world = "default";
            EntityStore entityStore = store.getExternalData();
            if (entityStore != null && entityStore.getWorld() != null) {
                world = entityStore.getWorld().getName();
            }

            Location deathLocation = new Location(world, pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
            lastPositionManager.set(playerUuid, deathLocation);
            LOGGER.atFine().log("[DeathListener] Saved death location for " + playerUuid);
        } catch (Exception e) {
            LOGGER.atWarning().log("[DeathListener] Error: " + e.getMessage());
        }
    }

    @Override
    public void onComponentSet(@NonNullDecl Ref<EntityStore> ref, @NullableDecl DeathComponent deathComponent, @NonNullDecl DeathComponent t1, @NonNullDecl Store<EntityStore> store, @NonNullDecl CommandBuffer<EntityStore> commandBuffer) {}

    @Override
    public void onComponentRemoved(@NonNullDecl Ref<EntityStore> ref, @NonNullDecl DeathComponent deathComponent, @NonNullDecl Store<EntityStore> store, @NonNullDecl CommandBuffer<EntityStore> commandBuffer) {}

    @NullableDecl
    @Override
    public Query<EntityStore> getQuery() { return Query.any(); }
}
