/*
    @author Hertz
    @version 1.0
*/

var KJSUtils = Java.loadClass('dev.latvian.mods.kubejs.util.UtilsJS');

StartupEvents.registry('palladium:abilities', (event) => {
    event.create('arrzenhanced:forcefield')
    .icon(palladium.createItemIcon('palladium:vibranium_circuit'))
    .addProperty('particleOptions', 'string', '1.000 0.533 0 1', 'List in the format "R G B A"')
    .firstTick((entity, entry, holder, enabled) => {
        if (enabled) {
            return
        }
    })
    .tick((entity, entry, holder, enabled) => global.enhancedForcefield(entity, entry, holder, enabled))
    .lastTick((entity, entry, holder, enabled) => {
        if (enabled) {
            return
        }
    });
});

global.enhancedForcefield = (entity, entry, holder, enabled) => {
    if (enabled) {
        let options = entry.getPropertyByName('particleOptions');
        let player = entity;
        let lookAngle = entity.getLookAngle().scale(1.5);

        // Player position and target location
        let playerLocation = Vec3d(player.getX(), player.getY(), player.getZ());
        let targetLocation = Vec3d(
            playerLocation.x() + lookAngle.x(),
            playerLocation.y() + lookAngle.y(),
            playerLocation.z() + lookAngle.z()
        );

        // Particle type
        let particle = Utils.particleOptions('dust ' + options);

        // Horizontal offsets: right and left vectors
        let rightVec = lookAngle.cross(new Vec3d(0, 1, 0)).normalize();
        let leftVec = rightVec.scale(-1);

        // Array to define horizontal offsets
        // let horizontalOffsets = [-0.5, -0.25, 0, 0.25, 0.5, 0.75, 1, 1.25, 1.5]
        // let horizontalOffsets = [-0.8, -0.3, 0.1, 0.5, 0.9, 1.2, 1.7]
        let horizontalOffsets = [-0.8, -0.4, -0.1, 0.3, 0.6, 1.0, 1.3, 1.7]
        let maxHeight = 3.0 // Maximum height of particles
        let minHeight = 0.0
        let verticalSpacing = 0.3

        // Loop for vertical layers
        if (player.age % 3 == 0) {
            for (let i = 0; i <= maxHeight; i += verticalSpacing) {
                // Spawn center particle
                player.getLevel().spawnParticles(particle, true, targetLocation.x(), targetLocation.y() + i, targetLocation.z(), 0, 0, 0, 1, 0);
    
                // Loop through horizontal offsets
                horizontalOffsets.forEach(offset => {
                    let scaledRight = rightVec.scale(offset);
                    let scaledLeft = leftVec.scale(offset);
    
                    // Right-side particles
                    player.getLevel().spawnParticles(particle, true, targetLocation.x() + scaledRight.x(), targetLocation.y() + i + scaledRight.y(), targetLocation.z() + scaledRight.z(), 0, 0, 0, 1, 0);
    
                    // Left-side particles
                    player.getLevel().spawnParticles(particle, true, targetLocation.x() + scaledLeft.x(), targetLocation.y() + i + scaledLeft.y(), targetLocation.z() + scaledLeft.z(), 0, 0, 0, 1, 0);
                });
            }
        }

        let maxOffset = horizontalOffsets[horizontalOffsets.length - 1]

        let aabb = AABB.of(
            targetLocation.x() - maxOffset,
            targetLocation.y() + minHeight,
            targetLocation.z() - maxOffset,
            targetLocation.x() + maxOffset,
            targetLocation.y() + maxHeight,
            targetLocation.z() + maxOffset
        );
        let blacklist = [
            'minecraft:potion',
            'minecraft:arrow',
            'minecraft:snowball',
            'minecraft:egg',
            'minecraft:spectral_arrow',
            'minecraft:dragon_fireball',
            'minecraft:shulker_bullet',
            'minecraft:small_fireball',
            'minecraft:fireball',
            'minecraft:llama_spit',
            'palladium:custom_projectile',
        ]
        player.getLevel().getEntitiesWithin(aabb).forEach(target => {
            if (!blacklist.includes(target.type)) {
                if (target != player) {
                    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))
                    if (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)
                    }
                }
            } else {
                target.kill()
            }
        })
    }
};


global.enhancedForcefieldOld = (entity, entry, holder, enabled) => {
    if (enabled) {
        let options = entry.getPropertyByName('particleOptions')
        let player = entity
        let lookAngle = entity.getLookAngle().scale(1.5)
        let playerLocation = Vec3d(
            player.getX(),
            (player.getY() + 0.0), // formerly 1.0
            player.getZ()
        )
        let targetLocation = Vec3d(
            (playerLocation.x() + lookAngle.x()),
            (playerLocation.y() + lookAngle.y()),
            (playerLocation.z() + lookAngle.z())
        )
        let particle = Utils.particleOptions('dust ' + options)
        let rightVec = lookAngle.cross(new Vec3d(0,1,0)).normalize()
        let leftVec = lookAngle.cross(new Vec3d(0,1,0)).normalize().scale(-1)
        let partPosRight = Vec3d(
            (targetLocation.x() + rightVec.x()),
            (targetLocation.y() + rightVec.y()),
            (targetLocation.z() + rightVec.z())
        )
        let partPosRightMidLeft = Vec3d(
            (targetLocation.x() + rightVec.x()*0.25),
            (targetLocation.y() + rightVec.y()*0.25),
            (targetLocation.z() + rightVec.z()*0.25)
        )
        let partPosRightMid = Vec3d(
            (targetLocation.x() + rightVec.x()*0.5),
            (targetLocation.y() + rightVec.y()*0.5),
            (targetLocation.z() + rightVec.z()*0.5)
        )
        let partPosRightMidRight = Vec3d(
            (targetLocation.x() + rightVec.x()*0.75),
            (targetLocation.y() + rightVec.y()*0.75),
            (targetLocation.z() + rightVec.z()*0.75)
        )
        let partPosLeft = Vec3d(
            (targetLocation.x() + leftVec.x()),
            (targetLocation.y() + leftVec.y()),
            (targetLocation.z() + leftVec.z())
        )
        let partPosLeftMidLeft = Vec3d(
            (targetLocation.x() + leftVec.x()*0.25),
            (targetLocation.y() + leftVec.y()*0.25),
            (targetLocation.z() + leftVec.z()*0.25)
        )
        let partPosLeftMid = Vec3d(
            (targetLocation.x() + leftVec.x()*0.5),
            (targetLocation.y() + leftVec.y()*0.5),
            (targetLocation.z() + leftVec.z()*0.5)
        )
        let partPosLeftMidRight = Vec3d(
            (targetLocation.x() + leftVec.x()*0.75),
            (targetLocation.y() + leftVec.y()*0.75),
            (targetLocation.z() + leftVec.z()*0.75)
        )
        for (var i = 0; i <= 3.0; i += 0.30) {
            player.getLevel().spawnParticles(particle, true, targetLocation.x(), targetLocation.y()+i, targetLocation.z(), 0, 0, 0, 1, 0)
            player.getLevel().spawnParticles(particle, true, partPosRight.x(), partPosRight.y()+i, partPosRight.z(), 0, 0, 0, 1, 0)
            player.getLevel().spawnParticles(particle, true, partPosLeft.x(), partPosLeft.y()+i, partPosLeft.z(), 0, 0, 0, 1, 0)
            player.getLevel().spawnParticles(particle, true, partPosRightMid.x(), partPosRightMid.y()+i, partPosRightMid.z(), 0, 0, 0, 1, 0)
            player.getLevel().spawnParticles(particle, true, partPosLeftMid.x(), partPosLeftMid.y()+i, partPosLeftMid.z(), 0, 0, 0, 1, 0)


            player.getLevel().spawnParticles(particle, true, partPosRightMidLeft.x(), partPosRightMidLeft.y()+i, partPosRightMidLeft.z(), 0, 0, 0, 1, 0)
            player.getLevel().spawnParticles(particle, true, partPosRightMidRight.x(), partPosRightMidRight.y()+i, partPosRightMidRight.z(), 0, 0, 0, 1, 0)
            player.getLevel().spawnParticles(particle, true, partPosLeftMidLeft.x(), partPosLeftMidLeft.y()+i, partPosLeftMidLeft.z(), 0, 0, 0, 1, 0)
            player.getLevel().spawnParticles(particle, true, partPosLeftMidRight.x(), partPosLeftMidRight.y()+i, partPosLeftMidRight.z(), 0, 0, 0, 1, 0)
        }
    }
}