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

const breath_damage = 4;
const on_fire_duration = 2;
const breath_radius = 5.0;
const breath_vertical_knockback = 0.3;
const breath_horizontal_knockback = 1.5;

const fireball_damage = 4;
const fireball_radius = 5.0;
const fireball_vertical_knockback = 0.3;
const fireball_horizontal_knockback = 1.0;

const nova_damage = 2;
const nova_radius = 3.0;
const nova_vertical_knockback = 0.3;
const nova_horizontal_knockback = 3.0;

export function fireball(sourceEntity) {
   
    let evt_location = sourceEntity.location;
    let dimension = sourceEntity.dimension.id;

    try 
    {
        for (let entity of mc.world.getDimension(dimension).getEntities({ location: evt_location,  excludeFamilies: ["npc","player","projectile","prop"], maxDistance: fireball_radius})) 
        {
            entity.applyDamage(fireball_damage);
            entity.applyKnockback(entity.location.x - evt_location.x, entity.location.z - evt_location.z, fireball_horizontal_knockback , fireball_vertical_knockback);
        }
    } 
    catch (error) {}
}

export function nova(sourceEntity) {
   
    let evt_location = sourceEntity.location;
    let dimension = sourceEntity.dimension.id;

    try 
    {
        for (let entity of mc.world.getDimension(dimension).getEntities({ location: evt_location,  excludeFamilies: ["npc","player","projectile","prop"], maxDistance: nova_radius})) 
        {
            entity.applyDamage(nova_damage);
            entity.applyKnockback(entity.location.x - evt_location.x, entity.location.z - evt_location.z, nova_horizontal_knockback , nova_vertical_knockback);
        }
    } 
    catch (error) {}
}

export function breath(sourceEntity) {
   
    let evt_location = sourceEntity.location;
    let dimension = sourceEntity.dimension.id;
    let view_vector = sourceEntity.getViewDirection();
    view_vector = {x: view_vector.x, y: 0, z: view_vector.z};

    try 
    {
        for (let entity of mc.world.getDimension(dimension).getEntities({ location: evt_location,  excludeFamilies: ["npc","player","projectile","prop"], maxDistance: breath_radius})) 
        {
            if(isEntityinCone(evt_location, entity.location, view_vector, 100))
            {
                entity.applyDamage(breath_damage);
                //entity.setOnFire(on_fire_duration, true);
                entity.applyKnockback(entity.location.x - evt_location.x, entity.location.z - evt_location.z, breath_horizontal_knockback , breath_vertical_knockback);
            }
        }
    } 
    catch (error) {}
}

export function isEntityinCone( source_location, target_location, view_vector, deviation_angle)
{
  let target_vector = {x: source_location.x-target_location.x, y: source_location.z-target_location.z, z: 0};

  let dot = (p1, p2)=>  p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;
  let mag = ({x, y, z}) => Math.hypot(x, y, z);

  let angle = Math.acos(dot(view_vector, target_vector) / (mag(view_vector) * mag(target_vector)));
  angle = angle*(180/Math.PI);
  angle = Math.abs(angle-180);

  if(angle < deviation_angle) return true;
  return false;
}