import * as mc from '@minecraft/server';

const cooldown = 20;
const damage = 5;
const radius = 4;
const vertical_knockback = 0.7;
const horizontal_knockback = 2.5;

export function lazer(sourceEntity) {
   
    let view_vector = sourceEntity.getViewDirection();
    let evt_location = sourceEntity.getHeadLocation();

    //let entity_raycast_hit = sourceEntity.dimension.getEntitiesFromRay(sourceEntity.getHeadLocation(), sourceEntity.getViewDirection(), { maxDistance: 64 });
    //    if (entity_raycast_hit === undefined) return;
    //    let distance = entity_raycast_hit[0].distance;
    //    mc.world.sendMessage("dist: "+ distance);
    //    mc.world.sendMessage("entity: "+ entity_raycast_hit.length);
    let block_raycast_hit = sourceEntity.dimension.getBlockFromRay(sourceEntity.getHeadLocation(), sourceEntity.getViewDirection(), { includeLiquidBlocks: false, includePassableBlocks: false, maxDistance: 64 });
    if (block_raycast_hit === undefined) return;
    let block = block_raycast_hit.block;
    let block_location = block.location;
    let distance = getDistance(evt_location, block_location)

    let mvm = new mc.MolangVariableMap();
    mvm.setFloat(`variable.dir_x`, view_vector.z);
    mvm.setFloat(`variable.dir_y`, sourceEntity.getRotation().x);
    mvm.setFloat(`variable.dir_z`, -view_vector.x);
    mvm.setFloat(`variable.stretch`, distance);
    
    mc.world.getDimension('overworld').spawnParticle('pb:lazerbeam_violet_rotate', evt_location, mvm); 

    //mc.world.sendMessage("x: "+ view_vector.x +"  z: "+ view_vector.z);
    //mc.world.sendMessage("x: "+ sourceEntity.getRotation().x );

    mvm = new mc.MolangVariableMap();
    mvm.setFloat(`variable.dir_x`, view_vector.x);
    mvm.setFloat(`variable.dir_y`, view_vector.y);
    mvm.setFloat(`variable.dir_z`, view_vector.z);
    mvm.setFloat(`variable.stretch`, distance);

    mc.world.getDimension('overworld').spawnParticle('pb:lazerbeam_violet_script', evt_location, mvm); 
}

export function lazerToNearby(sourceEntity, num) {
   
    if(num == 0) return;
    let target = mc.world.getDimension(sourceEntity.dimension.id).getEntities({ location: sourceEntity.location, closest: num, maxDistance: 32 });
    if (target == undefined) return;
    for (let index = 0; index < target.length-1; index++) {
        //mc.world.sendMessage("["+index+"]: "+ target[index].typeId );
        lazerBetweenPoints(target[index], target[index+1]);
    }
}

export function lazerBetweenPoints(originEntity, targetEntity) {
   
    let target = targetEntity.getHeadLocation();
    let origin = originEntity.getHeadLocation();

    target = { x: target.x, y: target.y - 1, z: target.z };
    origin = { x: origin.x, y: origin.y - 1, z: origin.z };

    let direction = { x: target.x - origin.x, y: target.y - origin.y, z: target.z - origin.z }
    let direction_normalized = locationNormalize(direction);
    let distance = getDistance(origin, target);

    let midpoint = { x: origin.x + direction_normalized.x*distance/2, y: origin.y + direction_normalized.y*distance/2, z: origin.z + direction_normalized.z*distance/2 }
 
    let mvm = new mc.MolangVariableMap();
    mvm.setFloat(`variable.dir_x`, direction_normalized.x);
    mvm.setFloat(`variable.dir_y`, direction_normalized.y);
    mvm.setFloat(`variable.dir_z`, direction_normalized.z);
    mvm.setFloat(`variable.distance`, distance);

    mc.world.getDimension('overworld').spawnParticle('pb:lazer_soft_90', midpoint, mvm);
    mc.world.getDimension('overworld').spawnParticle('pb:lazer_soft', midpoint, mvm);

    mc.world.getDimension('overworld').spawnParticle('pb:physical_line_sparks', target); 
}

export function lazerBetweenLocations(target, origin) {

    target = { x: target.x, y: target.y - 1, z: target.z };
    origin = { x: origin.x, y: origin.y - 1, z: origin.z };

    let direction = { x: target.x - origin.x, y: target.y - origin.y, z: target.z - origin.z }
    let direction_normalized = locationNormalize(direction);
    let distance = getDistance(origin, target);

    let midpoint = { x: origin.x + direction_normalized.x*distance/2, y: origin.y + direction_normalized.y*distance/2, z: origin.z + direction_normalized.z*distance/2 }
 
    let mvm = new mc.MolangVariableMap();
    mvm.setFloat(`variable.dir_x`, direction_normalized.x);
    mvm.setFloat(`variable.dir_y`, direction_normalized.y);
    mvm.setFloat(`variable.dir_z`, direction_normalized.z);
    mvm.setFloat(`variable.distance`, distance);

    mc.world.getDimension('overworld').spawnParticle('pb:lazer_soft_90', midpoint, mvm);
    mc.world.getDimension('overworld').spawnParticle('pb:lazer_soft', midpoint, mvm);

    mc.world.getDimension('overworld').spawnParticle('pb:physical_line_sparks', target); 
}

function getDistance(a, b) {
    const dx = b.x - a.x;
    const dy = b.y - a.y;
    const dz = b.z - a.z;
    const distance = Math.hypot(dx, dy, dz);
    return distance;
}

function getLength(location) {
    return Math.hypot(location.x, location.y, location.z);
}

function locationNormalize(location) {
    const magnitude = getLength(location);
    const DirectionX = location.x / magnitude;
    const DirectionY = location.y / magnitude;
    const DirectionZ = location.z / magnitude;
    return { x: DirectionX, y: DirectionY, z: DirectionZ };
}