import { WEAPON_EFFECT_STATS, blacklistedEnemy, BASE_DAMAGE } from "./data";
import { system, MolangVariableMap } from "@minecraft/server";
import { demonicSwordExplosion } from "./weaponEffectHandler";
import { getRandomNumber } from "./utils/helpers";


function sleep(tick) {
  return new Promise(resolve => {
    system.runTimeout(() => {
      resolve(tick)
    }, tick)
  })
}

export async function woodenBallCageStop(event) {
  const projectile = event.sourceEntity
  
  projectile.runCommand(`/particle minecraft:huge_explosion_emitter ~~~`)
  projectile.runCommand(`/execute positioned ~~~ run damage @e[r=4, family=mob] 12`)
  projectile.runCommand(`/execute positioned ~~~ run playsound random.explode @a[r=16]`)
  projectile.triggerEvent("4ks_wp:despawn")
}

export async function swordRolloutHitBlock(event) {
  const projectile = event.projectile
  const dimension = event.dimension
  
  dimension.runCommand(`/particle minecraft:huge_explosion_emitter ${event.location.x} ${event.location.y} ${event.location.z}`)
  dimension.runCommand(`/execute positioned ${event.location.x} ${event.location.y} ${event.location.z} run damage @e[r=4, family=mob] 12`)
  dimension.runCommand(`/execute positioned ${event.location.x} ${event.location.y} ${event.location.z} run playsound random.explode @a[r=16]`)
  projectile.triggerEvent("4ks_wp:despawn")
}

export async function swordRolloutHitEntity(victim, projectile) {
  projectile.runCommand(`/particle minecraft:huge_explosion_emitter ~~~`)
  projectile.runCommand(`/damage @e[rm=0.1,family=mob,r=4] 12 none`)
  projectile.runCommand(`/playsound random.explode @a[r=16]~~~`)
  projectile.triggerEvent("4ks_wp:despawn")
}

export async function sculkArrowHitEntity(victim) {
  victim?.runCommand(`/particle 4ks_wp:lapis_explosion_blue ~~1~`)
  victim?.runCommand(`/damage @e[rm=0.1,family=mob,r=4] 9 entity_attack entity @p`)
}

export async function sculkArrowHitBlock(event) {
  const projectile = event.projectile
  const dimension = event.dimension
  dimension.runCommand(`/particle 4ks_wp:lapis_explosion_blue ${event.location.x} ${event.location.y + 1} ${event.location.z}`)
  dimension.runCommand(`/execute positioned ${event.location.x} ${event.location.y + 1} ${event.location.z} run damage @e[rm=0.1,family=mob,r=4] 9 entity_attack entity @p`)
}

function applyKnockbackFromEntity(centerEntity, victim, strength, vstrength) {
  // Get the positions of the player and victim
  let playerPosition = centerEntity?.location;  // assuming this is a Vector3
  let victimPosition = victim?.location;  // assuming this is a Vector3

  // Calculate the direction from the victim to the player (this is the vector from victim to player)
  let dx = playerPosition.x - victimPosition.x;
  let dy = playerPosition.y - victimPosition.y;
  let dz = playerPosition.z - victimPosition.z;

  // Normalize this vector (so the direction is consistent regardless of distance)
  let magnitude = Math.sqrt(dx * dx + dy * dy + dz * dz);
  dx /= magnitude;
  dy /= magnitude;
  dz /= magnitude;

  // Now calculate the knockback direction by inverting the vector (moving away from the player)
  dx = -dx;
  dy = -dy;
  dz = -dz;

  // Apply the knockback impulse (scaled by strength)
  victim?.clearVelocity();
  victim?.applyImpulse({
    x: dx * strength,
    y: vstrength,
    z: dz * strength
  });
}

export async function dragonEnderHitEntity(victim, source) {
  if (victim.typeId == "minecraft:player") return
  victim.runCommand("/summon 4ks_wp:dragon_ender_area ~~0.5~")
  victim.runCommand("/particle 4ks_wp:dragon_aoe_bow ~~0.5~")
}

export async function bedrockTornadoArrowHitEntity(victim, source) {
  if (victim.typeId == "minecraft:player") return
  applyKnockbackFromEntity(source, victim, 3, 2)
}

export function uraniumExplode(event) {
  event.sourceEntity.runCommand(`/particle 4ks_wp:explosion_green ~~1~`)
}

export function ironBowRain(event) {
  const source = event.sourceEntity
  if (!source) return
  const location = source.location;
  const dimension = source.dimension;
  const startX = location.x - 4.5;
  const startZ = location.z - 4.5;
  const height = location.y + 16;

  for (let i = 0; i < getRandomNumber(10, 15); i++) {

    const randomX = Math.floor(Math.random() * 9);
    const randomZ = Math.floor(Math.random() * 9);
    const randomY = getRandomNumber(-2, 2)
    dimension.spawnEntity("4ks_wp:iron_bow_arrow", {
      x: startX + randomX,
      y: height + randomY,
      z: startZ + randomZ
    });
  }

}

export async function divineBeamDamageSmall(event) {
  const entity = event.sourceEntity

  entity.runCommand(`/damage @e[family=mob, type=!armor_stand, r=2] ${WEAPON_EFFECT_STATS.divine_sword_beam_damage_per_tick} entity_attack entity @p`)
}

export async function divineBowHitEntity(victim) {
  if (victim.getDynamicProperty("4ks_wp:divine_bow_hit")) return
  victim.runCommand("/summon 4ks_wp:divine_beam_small ~ ~ ~")
  await sleep(40)
  if (!victim || !victim.isValid()) return
  victim?.setDynamicProperty("4ks_wp:divine_bow_hit", false)
}

export async function lapisProjectileBowHitEntity(victim) {
  victim?.runCommand(`/particle 4ks_wp:lapis_explosion_blue ~~1~`)
  victim?.runCommand(`/damage @e[rm=0.1,family=mob,r=4] 9 entity_attack entity @p`)
}

export async function handleArrowProjectileHitBlock(event) {
  const dimension = event.dimension
  const projectile = event.projectile
  const source = event.source
  if (!source) return
  const bowType = source.getDynamicProperty(`4ks_wp:last_used_bow`)
  if (!bowType) return
  try {
    if (bowType.includes("tnt_crossbow")) {
      dimension.runCommand(`/particle minecraft:huge_explosion_emitter ${projectile.location.x} ${projectile.location.y} ${projectile.location.z}`)
      dimension.runCommand(`/execute positioned ${projectile.location.x} ${projectile.location.y} ${projectile.location.z} run damage @e[r=4, family=mob] 11`)
      source.runCommand(`/playsound random.explode @a[r=16] ${projectile.location.x} ${projectile.location.y} ${projectile.location.z}`)
    }
    else if (bowType.includes("dragon")) {
      projectile.runCommand(`/summon 4ks_wp:dragon_crossbow_area ~~~`)
      projectile.runCommand(`/particle 4ks_wp:dragon_aoe_xbow ~~~`)
    }
    else if (bowType.includes("cryo_bow_special")) {
      projectile?.runCommand(`/effect @e[family=mob, r=${WEAPON_EFFECT_STATS.cryo_bow_slowness_radius}] slowness 255 ${WEAPON_EFFECT_STATS.cryo_bow_slowness_time} true`)
      projectile?.runCommand(`/damage @e[rm=0.1,family=mob,r=${WEAPON_EFFECT_STATS.cryo_bow_slowness_radius}] 9 entity_attack entity @p`)
      projectile?.runCommand("/playsound 4ks_wp.cryo_onuse @a[r=16] ~~~")
      const molangMap = new MolangVariableMap()
      molangMap.setVector3("variable.data", { x: WEAPON_EFFECT_STATS.cryo_bow_slowness_radius, y: 0, z: 0 })
      projectile.dimension.spawnParticle("4ks_wp:ice_aoe_2", projectile.location, molangMap);
    } else if (bowType.includes("flame") && bowType.includes("_bow_special")) {
      projectile?.runCommand(`/damage @e[rm=0.1,family=mob,r=4] 9 entity_attack entity @p`)
      const entities = projectile.dimension.getEntities({ location: projectile.location, maxDistance: 4, families: ["mob"] });
      for (const entity of entities) {
        entity.setOnFire(5, true)
        applyKnockbackFromEntity(projectile, entity, 2, 0)
      }
      projectile.runCommand("/playsound 4ks_wp.flame_onuse @a[r=16] ~~~")
      const molangMap = new MolangVariableMap()
      molangMap.setVector3("variable.data", { x: 4, y: 0, z: 0 })
      projectile.dimension.spawnParticle("4ks_wp:flame_area", projectile.location, molangMap);
      //dimension.createExplosion(event.location, 4, { breaksBlocks: false, causesFire: true })
    } else if (bowType.includes("sapphire")) {
      projectile.runCommand(`/tp @e[family=mob, r=6] ${event.projectile.location.x} ${event.projectile.location.y + 1} ${event.projectile.location.z}`)
      await sleep(4)
      projectile?.runCommand(`/damage @e[rm=0.1,family=mob,r=3] 9 entity_attack entity @p`)
      projectile?.runCommand(`/playsound random.explode @a[r=16] ~~~`)
      projectile?.runCommand(`/execute as @s positioned ~ ~1.5 ~ run particle 4ks_wp:explosion_purple_small ~~~`)
    } else if(bowType.includes("iron_bow_special")) {
      if(projectile.getDynamicProperty("4ks_wp:iron_bow_special")) return
      projectile.setDynamicProperty("4ks_wp:iron_bow_special", true)
      projectile?.runCommand(`/summon 4ks_wp:iron_bow_emitter ~~~`)
    }
  } catch (e) {

  }

}



const DAMAGE_RADIUS = [8, 5, 3];

function performChainAttack(center, chainLevel, damagedEntities, dimension) {
  if (chainLevel >= DAMAGE_RADIUS.length) return;

  const radius = DAMAGE_RADIUS[chainLevel];

  const entities = dimension
    .getEntities({
      location: center,
      maxDistance: radius,
      families: ["mob"]
    });

  for (const entity of entities) {
    if (damagedEntities.has(entity.id)) continue;

    entity.applyDamage(WEAPON_EFFECT_STATS.amethyst_bow_chain_attack_damage);
    damagedEntities.add(entity.id);
    entity.runCommand(`/particle 4ks_wp:amethyst_chain ~~~`)

    system.runTimeout(() => {
      performChainAttack(entity.location, chainLevel + 1, damagedEntities, dimension);
    }, 15);
  }
}

async function amethystBowSpecialProjectile(victim) {
  const location = victim.location

  victim.runCommand(`/playsound 4ks_wp.amethyst_onuse @a[r=16] ~~~`)
  performChainAttack(location, 0, new Set(), victim.dimension)
}

export async function demonBowHitEntity(victim) {
  if (victim.getDynamicProperty("4ks_wp:demon_bow_hit")) return
  victim?.setDynamicProperty("4ks_wp:demon_bow_hit", true)
  victim?.runCommand(`/effect @s levitation ${WEAPON_EFFECT_STATS.demonic_sword_levitation_length} ${WEAPON_EFFECT_STATS.demonic_sword_levitation_level} true`)
  victim?.runCommand("/particle 4ks_wp:demon_mob_affected ~~~")
  victim?.runCommand("/particle 4ks_wp:demon_floaty ~~~")
  await demonicSwordExplosion(victim)
  if (!victim || !victim.isValid()) return
  victim?.setDynamicProperty("4ks_wp:demon_bow_hit", false)
}

export async function handleArrowProjectile(victim, source) {
  if (!source) return
  const bowType = source.getDynamicProperty(`4ks_wp:last_used_bow`)
  if (!bowType) return

  let damage = BASE_DAMAGE[bowType.replace("4ks_wp:", "").replace("_loaded", "")]
  if (damage === undefined) return
  if (!source) return
  
  
  if (bowType.includes("_bow")) {
    const useDuration = 19999980 - source.getDynamicProperty(`4ks_wp:last_used_duration`)
    if (!bowType.includes("_long_bow")) {
      if (useDuration <= 15) damage = damage / 2
    } else if (bowType.includes("_long_bow"))
      damage = Math.min(damage, Math.floor(damage * (useDuration / 40)))
  }

  if(bowType.includes("_long_bow")) {
    const mainHand = source.getComponent("minecraft:equippable").getEquipment("Mainhand")
    const havePower = mainHand.getComponent("minecraft:enchantable").getEnchantment("power")
    
    if(havePower) {
      damage = damage + (damage * (0.25 * (havePower.level + 1)))
      
    }
  }
  const health = victim.getComponent('minecraft:health')
  health.setCurrentValue(health.currentValue - damage)

  
  if (bowType.includes("flame")) {
    victim.setOnFire(WEAPON_EFFECT_STATS.flame_bows_fire_duration, true)
  } else if (bowType.includes("cryo")) {
    victim.runCommand(`/effect @s slowness ${WEAPON_EFFECT_STATS.cryo_bows_slowness_duration} ${WEAPON_EFFECT_STATS.cryo_bows_slowness_level}`)
  }

  if (bowType.includes("_bow_special")) {
    if (bowType.includes("amethyst")) {
      amethystBowSpecialProjectile(victim)
    } else if (bowType.includes("cryo")) {
      victim?.runCommand(`/effect @e[family=mob, r=${WEAPON_EFFECT_STATS.cryo_bow_slowness_radius}] slowness 255 ${WEAPON_EFFECT_STATS.cryo_bow_slowness_time} true`)
      //victim?.runCommand(`/summon 4ks_wp:cryo_bow_area ~~~`)
      victim?.runCommand(`/damage @e[rm=0.1,family=mob,r=${WEAPON_EFFECT_STATS.cryo_bow_slowness_radius}] 9 entity_attack entity @p`)
      victim.runCommand("/playsound 4ks_wp.cryo_onuse @a[r=16] ~~~")
      const molangMap = new MolangVariableMap()
      molangMap.setVector3("variable.data", { x: WEAPON_EFFECT_STATS.cryo_bow_slowness_radius, y: 0, z: 0 })
      victim.dimension.spawnParticle("4ks_wp:ice_aoe_2", victim.location, molangMap);
    } else if (bowType.includes("flame")) {
      victim?.runCommand(`/damage @e[rm=0.1,family=mob,r=4] 9 entity_attack entity @p`)
      const entities = victim?.dimension.getEntities({ location: victim.location, maxDistance: 4, families: ["mob"] });
      for (const entity of entities) {
        entity.setOnFire(5, true)
        applyKnockbackFromEntity(source, entity, 2, 0)
      }
      victim.runCommand("/playsound 4ks_wp.flame_onuse @a[r=16] ~~~")
      const molangMap = new MolangVariableMap()
      molangMap.setVector3("variable.data", { x: 4, y: 0, z: 0 })
      victim.dimension.spawnParticle("4ks_wp:flame_area", victim.location, molangMap);
    } else if (bowType.includes("sapphire")) {
      victim.runCommand(`/tp @e[family=mob, r=6] ~~~`)
      await sleep(4)
      victim?.runCommand(`/damage @e[rm=0.1,family=mob,r=3] 9 entity_attack entity @p`)
      victim?.runCommand(`/playsound random.explode @a[r=16] ~~~`)
      victim?.runCommand(`/execute as @s positioned ~ ~1.5 ~ run particle 4ks_wp:explosion_purple_small ~~~`)
    } else if (bowType.includes("gold")) {
      const projectileCount = 24; // Increased number of directions for better circular spread
      const baseSpeed = 2.5; // Increased base speed for better shockwave effect
      victim.runCommand(`/particle 4ks_wp:gold_hit ~~0.5~`)
      for (let i = 0; i < projectileCount; i++) {
        const angle = (Math.PI * 2 * i) / projectileCount; // Evenly distributed angles in radians
        const xDir = Math.cos(angle);
        const zDir = Math.sin(angle);

        const headLocation = victim.getHeadLocation();
        const viewDirection = victim.getViewDirection();
        const projectile = victim.dimension.spawnEntity("4ks_wp:gold_bow_arrow", {
          x: headLocation.x + viewDirection.x * 2,
          y: headLocation.y + viewDirection.y * 2,
          z: headLocation.z + viewDirection.z * 2
        });

        const projectileComp = projectile.getComponent('minecraft:projectile');
        const velocity = {
          x: xDir * baseSpeed,
          y: 0.2, // Slight upward angle for visual effect
          z: zDir * baseSpeed
        };
        projectileComp?.shoot(velocity);

        // Add small random variation to create spread effect
        projectile.applyImpulse({
          x: (Math.random() - 0.5) * 0.3,
          y: (Math.random() - 0.5) * 0.3,
          z: (Math.random() - 0.5) * 0.3
        });
      }
    } else if (bowType.includes("iron")) {
      victim?.runCommand(`/summon 4ks_wp:iron_bow_emitter ~~~`)
    }
  }
  
  if (bowType.includes("crossbow")) {
    if (bowType.includes("tnt")) {
      
      victim.runCommand(`/particle minecraft:huge_explosion_emitter ~~~`)
      victim.runCommand(`/damage @e[r=4, family=mob] 11`)
      victim.runCommand(`/playsound random.explode @a[r=16] ~~~`)
      
    }
    else if (bowType.includes("ender"))
      victim.runCommand(`/tp ~ ~${WEAPON_EFFECT_STATS.ender_crossbow_teleport_height} ~`)
    else if (bowType.includes("wither"))
      victim.runCommand(`/effect @s wither ${WEAPON_EFFECT_STATS.wither_bow_wither_duration} ${WEAPON_EFFECT_STATS.wither_bow_wither_level}`)
    else if (bowType.includes("dragon")) {
      victim.runCommand(`/summon 4ks_wp:dragon_crossbow_area ~~~`)
      victim.runCommand("/particle 4ks_wp:dragon_aoe_xbow ~~0.5~")
    }
  }


}

async function projectileMovementControl(projectile, projectileSpeed, timeAlive) {
  if (projectile == undefined || !projectile.isValid()) return
  const player = projectile.dimension.getEntities({ location: projectile.location, type: "minecraft:player", closest: 1 })[0]
  const projectileDirection = {
    x: player.getViewDirection().x * projectileSpeed,
    y: player.getViewDirection().y * projectileSpeed,
    z: player.getViewDirection().z * projectileSpeed,
  };
  while (timeAlive-- > 0) {
    await sleep(1)
    if (projectile == undefined || !projectile.isValid()) return
    projectile.clearVelocity();
    projectile.applyImpulse(projectileDirection);
  }
  if (projectile == undefined || !projectile.isValid()) return
  projectile.triggerEvent("4ks_wp:despawn")
}

export async function electricBallProjectile(projectile) {
  projectileMovementControl(projectile, WEAPON_EFFECT_STATS.electric_ball_speed, WEAPON_EFFECT_STATS.electric_ball_projectile_alive_time)
}

export async function uraniumBallProjectile(projectile) {
  projectileMovementControl(projectile, WEAPON_EFFECT_STATS.uranium_ball_speed, WEAPON_EFFECT_STATS.uranium_ball_projectile_alive_time)
}
export async function lapisSwordProjectile(projectile) {
  projectileMovementControl(projectile, WEAPON_EFFECT_STATS.lapis_sword_wave_speed, WEAPON_EFFECT_STATS.lapis_sword_projectile_alive_time)
}
export async function platinumSwordProjectile(projectile) {
  projectileMovementControl(projectile, WEAPON_EFFECT_STATS.platinum_sword_projectile_speed, WEAPON_EFFECT_STATS.platinum_sword_projectile_alive_time)
}
export async function diamondSwordProjectile(projectile) {
  projectileMovementControl(projectile, WEAPON_EFFECT_STATS.diamond_sword_projectile_speed, WEAPON_EFFECT_STATS.diamond_sword_projectile_alive_time)
}
export async function rubySwordProjectile(projectile) {
  projectileMovementControl(projectile, WEAPON_EFFECT_STATS.ruby_sword_projectile_speed, WEAPON_EFFECT_STATS.ruby_sword_projectile_alive_time)
}
export async function dragonSwordProjectile(projectile) {
  projectileMovementControl(projectile, WEAPON_EFFECT_STATS.dragon_sword_projectile_speed, WEAPON_EFFECT_STATS.dragon_sword_projectile_alive_time)

}

export async function uraniumBallProjectileHit(event) {
  const projectile = event.projectile
  if (projectile == undefined || !projectile.isValid()) return
  projectile.runCommand(`/damage @e[family=mob, type=!armor_stand, rm=0.1,r=${WEAPON_EFFECT_STATS.uranium_ball_explosion_radius}] ${WEAPON_EFFECT_STATS.uranium_ball_projectile_damage} entity_attack entity @p`)
  for (const victim of projectile.dimension.getEntities({ maxDistance: WEAPON_EFFECT_STATS.uranium_ball_explosion_radius, location: projectile.location, excludeTypes: blacklistedEnemy })) {
    if (victim == undefined || !victim.isValid() || victim.typeId == projectile.typeId || victim.typeId == "minecraft:item" || victim.typeId == "minecraft:player") continue
    const knockbackStrength = WEAPON_EFFECT_STATS.uranium_ball_knockback_strength.horizontal
    const knockbackVerticalStrength = WEAPON_EFFECT_STATS.uranium_ball_knockback_strength.vertical
    const projectileLocation = projectile.location;
    const victimPosition = victim.location;
    victimPosition.x = (1 / (victimPosition.x - projectileLocation.x) * knockbackStrength)
    victimPosition.z = (1 / (victimPosition.z - projectileLocation.z) * knockbackStrength)

    victim.clearVelocity()
    victim.applyImpulse({ x: victimPosition.x, y: knockbackVerticalStrength, z: victimPosition.z })
  }
  if (WEAPON_EFFECT_STATS.uranium_ball_projectile_remove_on_hit) {
    await sleep(1)
    if (projectile == undefined || !projectile.isValid()) return
    projectile.triggerEvent("4ks_wp:despawn")
  }
}
export async function lapisSwordProjectileHitBlock(event) {
  const projectile = event.projectile
  if (projectile == undefined || !projectile.isValid() || projectile.getDynamicProperty("4ksrubyhit")) return
  projectile.setDynamicProperty("4kswphit", true)
  projectile.runCommand("/particle 4ks_wp:projectile_hit_blue ~~1~")
  projectile.runCommand("/particle 4ks_wp:projectile_hit2_blue ~~1~")
  projectile.triggerEvent("4ks_wp:despawn")

}
export async function lapisProjectileLoop(event) {
  const projectile = event.sourceEntity
  if (projectile == undefined || !projectile.isValid() || projectile.getDynamicProperty("4ksrubyhit")) return
  projectile.setDynamicProperty("4kswphit", true)

  projectile.runCommand("/particle 4ks_wp:projectile_hit_blue ~~1~")
  projectile.runCommand("/particle 4ks_wp:projectile_hit2_blue ~~1~")
  for (const victim of projectile.dimension.getEntities({ excludeTypes: blacklistedEnemy, location: projectile.location, maxDistance: WEAPON_EFFECT_STATS.lapis_sword_wave_radius })) {
    if (victim == undefined || !victim.isValid() || victim.typeId == projectile.typeId || victim.typeId == "minecraft:item" || victim.typeId == "minecraft:player") continue
    const knockbackStrength = WEAPON_EFFECT_STATS.lapis_sword_wave_knockback_strength.horizontal
    const knockbackVerticalStrength = WEAPON_EFFECT_STATS.lapis_sword_wave_knockback_strength.vertical
    const projectileLocation = projectile.location;
    const victimPosition = victim.location;
    victimPosition.x = (1 / (victimPosition.x - projectileLocation.x) * knockbackStrength)
    victimPosition.z = (1 / (victimPosition.z - projectileLocation.z) * knockbackStrength)

    victim.applyDamage(WEAPON_EFFECT_STATS.lapis_sword_wave_damage)
    victim.clearVelocity()
    victim.applyImpulse({ x: victimPosition.x, y: knockbackVerticalStrength, z: victimPosition.z })

  }
}
export async function diamondSwordProjectileHit(event) {
  const projectile = event.projectile
  if (projectile == undefined || !projectile.isValid() || projectile.getDynamicProperty("4ksrubyhit")) return
  projectile.setDynamicProperty("4kswphit", true)
  projectile.runCommand(`/damage @e[family=mob, type=!armor_stand, rm=0.1,r=2] ${WEAPON_EFFECT_STATS.diamond_sword_projectile_damage} entity_attack entity @p`)
  projectile.runCommand("/playsound 4ks_wp.blaster.hit @a[r=64]")
  projectile.runCommand("/particle 4ks_wp:projectile_hit_white ~~1~")
  projectile.runCommand("/particle 4ks_wp:projectile_hit2_white ~~1~")
  if (WEAPON_EFFECT_STATS.diamond_sword_projectile_remove_on_hit) {
    await sleep(1)
    if (projectile == undefined || !projectile.isValid()) return
    projectile.triggerEvent("4ks_wp:despawn")
  }
}
export async function rubySwordProjectileHit(event) {
  const projectile = event.projectile
  if (projectile == undefined || !projectile.isValid() || projectile.getDynamicProperty("4ksrubyhit")) return
  projectile.setDynamicProperty("4ksrubyhit", true)
  projectile.runCommand(`/damage @e[family=mob, type=!armor_stand, rm=0.1,r=2] ${WEAPON_EFFECT_STATS.ruby_sword_projectile_damage} entity_attack entity @p`)
  projectile.runCommand("/playsound 4ks_wp.blaster.hit @a[r=64]")
  projectile.runCommand("/particle 4ks_wp:projectile_hit_red ~~1~")
  projectile.runCommand("/particle 4ks_wp:projectile_hit2_red ~~1~")
  if (WEAPON_EFFECT_STATS.ruby_sword_projectile_remove_on_hit) {
    await sleep(1)
    if (projectile == undefined || !projectile.isValid()) return
    projectile.triggerEvent("4ks_wp:despawn")
  }
}
export async function platinumSwordProjectileHit(event) {
  const projectile = event.projectile
  if (projectile == undefined || !projectile.isValid() || projectile.getDynamicProperty("4kswphit")) return
  projectile.setDynamicProperty("4kswphit", true)
  projectile.runCommand(`/damage @e[family=mob, type=!armor_stand, rm=0.1,r=${WEAPON_EFFECT_STATS.platinum_sword_explosion_radius}] ${WEAPON_EFFECT_STATS.platinum_sword_projectile_damage} entity_attack entity @p`)

  projectile.runCommand("/playsound 4ks_wp.blaster.hit @a[r=64]")
  projectile.runCommand("/particle 4ks_wp:projectile_hit_purple ~~1~")
  projectile.runCommand("/particle 4ks_wp:projectile_hit2_purple ~~1~")
  projectile.runCommand(`/particle 4ks_wp:plat_explode_1 ~~2~`)
  const molangMap = new MolangVariableMap()
  molangMap.setVector3("variable.data", { x: WEAPON_EFFECT_STATS.platinum_sword_explosion_radius, y: WEAPON_EFFECT_STATS.platinum_sword_lingering_time, z: 0 })
  event.dimension.spawnParticle("4ks_wp:plat_explode_2", projectile.location, molangMap);
  for (const victim of projectile.dimension.getEntities({ maxDistance: WEAPON_EFFECT_STATS.platinum_sword_explosion_radius, location: projectile.location, excludeTypes: blacklistedEnemy })) {
    if (victim == undefined || !victim.isValid() || victim.typeId == projectile.typeId || victim.typeId == "minecraft:item" || victim.typeId == "minecraft:player") continue
    const knockbackStrength = WEAPON_EFFECT_STATS.platinum_sword_knockback_strength.horizontal
    const knockbackVerticalStrength = WEAPON_EFFECT_STATS.platinum_sword_knockback_strength.vertical
    const projectileLocation = projectile.location;
    const victimPosition = victim.location;
    victimPosition.x = (1 / (victimPosition.x - projectileLocation.x) * knockbackStrength)
    victimPosition.z = (1 / (victimPosition.z - projectileLocation.z) * knockbackStrength)

    victim.clearVelocity()
    victim.applyImpulse({ x: victimPosition.x, y: knockbackVerticalStrength, z: victimPosition.z })
  }

  if (WEAPON_EFFECT_STATS.platinum_sword_projectile_remove_on_hit) {
    await sleep(1)
    if (projectile == undefined || !projectile.isValid()) return
    projectile.triggerEvent("4ks_wp:despawn")
  }
}
export async function dragonSwordProjectileHit(event) {
  const projectile = event.projectile
  const hitLocation = event.location
  if (projectile == undefined || !projectile.isValid() || projectile.getDynamicProperty("4ksrubyhit")) return
  projectile.setDynamicProperty("4kswphit", true)

  event.dimension.runCommand(`/particle 4ks_wp:projectile_hit_purple ${hitLocation.x} ${hitLocation.y + 1} ${hitLocation.z}`)
  event.dimension.runCommand(`/particle 4ks_wp:projectile_hit2_purple ${hitLocation.x} ${hitLocation.y + 1} ${hitLocation.z}`)
  // const molangMap = new MolangVariableMap()
  // molangMap.setVector3("variable.data", { x: WEAPON_EFFECT_STATS.dragon_sword_lingering_radius, y: WEAPON_EFFECT_STATS.dragon_sword_lingering_alive_time, z: 0 })
  event.dimension.runCommand(`/particle 4ks_wp:dragon_aoe_2 ${hitLocation.x} ${hitLocation.y + 1} ${hitLocation.z}`)

  const checkerEntity = event.dimension.spawnEntity("4ks_wp:dragon_lingering_checker", hitLocation)
  await sleep(WEAPON_EFFECT_STATS.dragon_sword_lingering_alive_time * 20)
  checkerEntity.triggerEvent("4ks_wp:despawn")
}