let ClientboundSetEntityMotionPacket = Java.loadClass('net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket');

StartupEvents.registry('palladium:abilities', (event) => {
    event.create('arrzenhanced:aerokinesis')
    .icon(palladium.createItemIcon('minecraft:compass'))
    .tick((entity, entry, holder, enabled) => global.aerokinesisFunc(entity, entry, holder, enabled));
});

global.aerokinesisFunc = (entity, entry, holder, enabled) => {
    if (enabled) {
        var player = entity;
        let particle = Utils.particleOptions('dust 0.94 0.94 0.94 2.25');

        for (var i = 0; i <= 5; i+=0.8) {
            let lookAngle = player.getLookAngle().scale(1 + i);
            let playerLocation = Vec3d(player.getX(), player.getY(), player.getZ());
            let perpendicular = Vec3d(-lookAngle.z(), 0, lookAngle.x()).normalize().scale(0.5);
            let leftTarget = Vec3d(
                playerLocation.x() + lookAngle.x() + perpendicular.x(),
                playerLocation.y() + lookAngle.y(),
                playerLocation.z() + lookAngle.z() + perpendicular.z()
            );
            let rightTarget = Vec3d(
                playerLocation.x() + lookAngle.x() - perpendicular.x(),
                playerLocation.y() + lookAngle.y(),
                playerLocation.z() + lookAngle.z() - perpendicular.z()
            );

            player.getLevel().spawnParticles(particle, true, leftTarget.x(), leftTarget.y() + 1.15, leftTarget.z(), 0, 0, 0, 1, 0);
            player.getLevel().spawnParticles(particle, true, rightTarget.x(), rightTarget.y() + 1.15, rightTarget.z(), 0, 0, 0, 1, 0);
        }
    
        // Get player's position and look vector
        var pos = player.getEyePosition(); // Player's current position
        var look = player.getLookAngle(); // Player's look vector (direction they are looking)
    
        // Offset for the start of the AABB (0.5 blocks in front of the player)
        var start = pos.add(look.scale(0.5));
        // Offset for the end of the AABB (7 blocks away from the player)
        var end = pos.add(look.scale(7));
    
        // Create an AABB
        var aabb = AABB.of(start.x(), start.y(), start.z(), end.x(), end.y(), end.z());
    
        // Get entities within the AABB
        player.getLevel().getEntitiesWithin(aabb).forEach(target => {
            if (target !== player) { // Avoid affecting the player themselves
                // Calculate the direction from the player to the entity
                let dx = target.getX() - player.getX()
                let dy = target.getY() - player.getY()
                let dz = target.getZ() - player.getZ()
                // let dist = Math.sqrt((dx * dx) + (dy * dy) + (dz * dz))
                let dist = 3.5
                let knockbackStrength = 1.2
                let vx = (dx / dist) * knockbackStrength
                let vy = (dy / dist) * knockbackStrength
                let vz = (dz / dist) * knockbackStrength
                target.setMotion(vx, vy, vz)
                if (target.isPlayer()) {
                    target.connection.send(new ClientboundSetEntityMotionPacket(target));
                }
            }
        })
    };
}