import * as MC from "@minecraft/server";
import { onHitEntity, run } from "./utilities";

const LUNAR_BLADE_STRENGTH = 12;

onHitEntity(({ damagingEntity, hitEntity }) => {
  if (damagingEntity.typeId === "minecraft:player") {
    const itemStack = damagingEntity
      .getComponent("minecraft:equippable")
      .getEquipmentSlot("Mainhand")
      .getItem();
    if (!itemStack) return;
    if (itemStack.typeId === "chronicoverride_llc:echo_sword") {
      damagingEntity.runCommand(`playsound sas.echo_sword.echo_sword_swing @s`);
      const entities = hitEntity.dimension.getEntities({
        excludeNames: [damagingEntity.name],
        families: ["monster"],
        location: hitEntity.location,
        maxDistance: 10,
      });
      if (
        hitEntity.getComponent("minecraft:type_family").hasTypeFamily("monster")
      ) {
        hitEntity.runCommand(`playsound shriek.sculk_shrieker @a[r=10]`);
        hitEntity.runCommand(
          `execute as @e[family=monster,r=10] at @s run particle minecraft:shriek_particle ~~~`
        );
      }
      entities.forEach((entity) => {
        entity.applyDamage(8);
      });
    }
    if (itemStack.typeId === "chronicoverride_llc:lunar_blade") {
      damagingEntity.runCommand(
        `playsound sas.lunar_blade.lunar_blade_swing @s`
      );
    }

    if (itemStack.typeId === "chronicoverride_llc:spectral_spear") {
      damagingEntity.runCommand(
        `playsound sas.spectral_spear.spectral_spear_attack1 @s`
      );
    }
  }
});

run((players) => {
  players.forEach((player) => {
    const mainhand = player
      .getComponent("minecraft:equippable")
      .getEquipmentSlot("Mainhand")
      .getItem();

    const hasLunarBlade = player.hasTag("chronicoverride_llc:has_lunar_blade");

    const isNight =
      MC.world.getTimeOfDay() >= 13000 && MC.world.getTimeOfDay() <= 23000;

    if (mainhand) {
      if (
        !hasLunarBlade &&
        mainhand.typeId === "chronicoverride_llc:lunar_blade" &&
        isNight
      ) {
        player.addTag("chronicoverride_llc:has_lunar_blade");
        player.runCommand(`effect @s strength infinite 0 true`);
      }
      if (
        hasLunarBlade &&
        mainhand.typeId === "chronicoverride_llc:lunar_blade" &&
        isNight
      ) {
        for (let y = 8; y >= -3; y--) {
          try {
            player.runCommand(
              `fill ~-8~${y}~-8 ~8~${y}~8 air [] replace light_block ["block_light_level"=${LUNAR_BLADE_STRENGTH}]`
            );
          } catch (error) { }
        }
        MC.system.runTimeout(() => {
          player.runCommand(
            `fill ~~~ ~~2~ light_block ["block_light_level"=${LUNAR_BLADE_STRENGTH}] replace air`
          );
        }, 0.5);
      }
    }
    if (
      !mainhand ||
      mainhand.typeId !== "chronicoverride_llc:lunar_blade" ||
      !isNight
    ) {
      if (hasLunarBlade) {
        player.removeTag("chronicoverride_llc:has_lunar_blade");
        player.runCommand(`effect @s clear strength`);
        for (let y = 8; y >= -3; y--) {
          try {
            player.runCommand(
              `fill ~-8~${y}~-8 ~8~${y}~8 air [] replace light_block ["block_light_level"=${LUNAR_BLADE_STRENGTH}]`
            );
          } catch (error) { }
        }
      }
    }
  });
}, 0);

MC.world.afterEvents.projectileHitBlock.subscribe((event) => {
  const projectile = event.projectile;

  if (!projectile || !projectile.isValid || projectile.typeId != "chronicoverride_llc:spectral_spear_proj") return;

  if (projectile.hasTag("chronicoverride_llc:is_on_ground")) {
    return;
  }

  MC.system.run(() => {
    const projectileComponent = projectile.getComponent("minecraft:projectile");
    if (!projectileComponent) {
      return;
    }

    const ownerTag = projectile.getTags().find(tag => tag.startsWith("spear_owner:"))
    const ownerName = ownerTag ? ownerTag.replace("spear_owner:", "") : null;
    const owner = ownerName ? MC.world.getPlayers().find(player => player.name === ownerName) : null;

    projectile.addTag("chronicoverride_llc:is_on_ground");

    // Find closest entity
    const entitiesToHit = projectile.dimension.getEntities({
      location: projectile.location,
      maxDistance: 3,
    }).filter(entity => entity.id !== projectile.id);

    entitiesToHit.forEach(e => e.applyDamage(7));

    for (let i = 0; i < 4; i++) {
      const rx = (Math.random() * 2 - 1).toFixed(2);
      const ry = (Math.random() * 2 - 1).toFixed(2);
      const rz = (Math.random() * 2 - 1).toFixed(2);
      projectile.runCommand(
        `particle minecraft:trial_omen_ambient ~${rx}~${ry}~${rz}`
      );
    }
    projectile.triggerEvent("chronicoverride_llc:is_on_ground");

    // Teleport projectile back to owner
    projectile.teleport(owner.location);

    // Add item back to owner's inventory if not in creative mode
    if (owner.getGameMode() === "Creative") return;

    const spectralSpearItemStack = new MC.ItemStack("chronicoverride_llc:spectral_spear");
    const inventory = owner.getComponent("minecraft:inventory").container;

    if (inventory.emptySlotsCount > 0) {
      inventory.addItem(spectralSpearItemStack);
    } else {
      owner.dimension.spawnItem(spectralSpearItemStack, owner.location);
    }
  })
});

MC.world.afterEvents.projectileHitEntity.subscribe((event) => {
  const target = event.getEntityHit().entity;
  const projectile = event.projectile;

  // Ensure the projectile is the spectral spear projectile
  if (projectile.typeId != "chronicoverride_llc:spectral_spear_proj") return;

  const family = target.getComponent("minecraft:type_family");
  if (!family.hasTypeFamily("spectral")) return;

  // If the target is a bonemonger, deal more damage
  if (target.typeId === "chronicoverride_llc:bonemonger") {
    target.applyDamage(30);
  } else {
    target.applyDamage(15);
  }

  // Particle effect on hit
  for (let i = 0; i < 4; i++) {
    const rx = (Math.random() * 2 - 1).toFixed(2);
    const ry = (Math.random() * 2 - 1).toFixed(2);
    const rz = (Math.random() * 2 - 1).toFixed(2);
    projectile.runCommand(
      `particle minecraft:trial_omen_ambient ~${rx}~${ry}~${rz}`
    );
  }
});

MC.world.afterEvents.itemReleaseUse.subscribe((event) => {
  const { itemStack, source } = event;

  if (itemStack.typeId === "chronicoverride_llc:spectral_spear") {
    const closestSpear = source.dimension.getEntities({
      families: ["spectral_spear"],
      location: source.location,
      closest: true,
    })[0];

    if (!closestSpear) {
      return;
    }

    source.runCommand(`playsound sas.spectral_spear.spectral_spear_attack2 @s`);

    closestSpear.addTag(`spear_owner:${source.name}`);
  }
});
