import * as mc from "@minecraft/server";
import * as selectors from "../utils/selectors";
import * as vector from "../utils/vector";
import * as umvuthi from "../entities/umvuthi";
import { playTpAnim } from "../playerAbilities";

const SUPERNOVA_LENGTH = 90;
const SUPERNOVA_DAMAGE_LENGTH = 80;

export function use(event) {
  const player = event.source;
  if (event.itemStack.getComponent("minecraft:durability").damage >= 3599) return;
  if (player.getDynamicProperty("hf_mzs:using_ability") === true) return;

  // Sunstrike
  if (!player.getDynamicProperty("hf_mzs:can_supernova") && !event.source.isSneaking && !event.source.isJumping) {
    const ray = player.dimension.getBlockFromRay(player.getHeadLocation(), player.getViewDirection(), {
      maxDistance: 6,
      includeLiquidBlocks: false,
      includePassableBlocks: false,
    });
    // Sunstrike
    if (ray !== undefined && ray.face === "Up") {
      if (player.getDynamicProperty("hf_mzs:sunstrike") > 0) return;
      const pos = vector.add(ray.block.location, { x: 0.5, y: 1, z: 0.5 });
      if (
        player.dimension.getBlockFromRay(pos, vector.up, {
          maxDistance: 200,
          includeLiquidBlocks: false,
          includePassableBlocks: false,
        })
      )
        return;
      if (player.getGameMode() !== "creative") {
        const newItem = item.clone();
        newItem.setDynamicProperty("hf_mzs:was_used", true);
        player.getComponent("equippable").setEquipment("Mainhand", newItem);
      }
      player.setDynamicProperty("hf_mzs:sunstrike", 15);
      const sunstrike = player.dimension.spawnEntity("hf_mzs:sunstrike", pos);
      sunstrike.setDynamicProperty("hf_mzs:caster_id", player.id);
    }
    // Solar flare
    else {
      if (player.getGameMode() !== "creative") {
        const newItem = event.itemStack.clone();
        newItem.setDynamicProperty("hf_mzs:was_used", true);
        player.getComponent("equippable").setEquipment("Mainhand", newItem);
      }
      event.itemStack.setDynamicProperty("hf_mzs:was_used", true);
      player.setDynamicProperty("hf_mzs:using_ability", true);
      player.runCommand("/playsound hf_mzs:misc.solar_flare @s");
      player.runCommand(
        `/titleraw @s actionbar {"rawtext":[{"translate":"actionbar.hf_mzs.suns_blessing_solar_flare"}]}`
      );
      playTpAnim(player, "animation.hf_mzs.suns_blessing.tp_solar_flare");
      player.getComponent("movement").setCurrentValue(0.05);
      //mc.world.sendMessage("Solar Flare");
      mc.system.runTimeout(() => {
        player.runCommand("/tp @s ~~~");
        player.runCommand("/particle hf_mzs:umvuthi_flare_flash ^^1^1");
        player.runCommand("/particle hf_mzs:umvuthi_flare_stars ^^1^1");

        const union = selectors.union(
          {
            location: player.location,
            maxDistance: umvuthi.SOLAR_FLARE_DIST,
            excludeFamilies: ["inanimate"],
          },
          ["mob", "player"],
          player.dimension,
          player.id
        );
        for (let i = 0; i < union.length; i++) {
          if (!union[i].isValid()) continue;
          const dir = vector.subtract(union[i].location, player.location);
          union[i].applyKnockback(dir.x, dir.z, umvuthi.SOLAR_FLARE_KB, umvuthi.SOLAR_FLARE_KB / 3);
          union[i].applyDamage(umvuthi.SOLAR_FLARE_DAMAGE, {
            cause: "entityAttack",
            damagingEntity: player,
          });
        }
        mc.system.runTimeout(() => {
          player.setDynamicProperty("hf_mzs:using_ability", false);
          player.getComponent("movement").setCurrentValue(0.1);
        }, umvuthi.SOLAR_FLARE_LENGTH - umvuthi.SOLAR_FLARE_HIT_KF);
      }, umvuthi.SOLAR_FLARE_HIT_KF);
    }
    return;
  }

  // Solar beam
  if (!player.getDynamicProperty("hf_mzs:can_supernova") && event.source.isSneaking && !event.source.isJumping) {
    player.setDynamicProperty("hf_mzs:using_ability", true);
    player.runCommand(`/playsound hf_mzs:misc.laser @s`);
    player.runCommand(`/titleraw @s actionbar {"rawtext":[{"translate":"actionbar.hf_mzs.suns_blessing_solar_beam"}]}`);
    playTpAnim(player, "animation.hf_mzs.suns_blessing.tp_solar_beam_start");
    player.getComponent("movement").setCurrentValue(0.05);

    if (player.getGameMode() !== "creative") {
      const newItem = event.itemStack.clone();
      newItem.setDynamicProperty("hf_mzs:was_used", true);
      newItem.getComponent("minecraft:durability").damage = Math.min(
        newItem.getComponent("minecraft:durability").damage + 300,
        3600
      );
      player.getComponent("equippable").setEquipment("Mainhand", newItem);
    }

    mc.system.runTimeout(() => {
      player.setDynamicProperty("hf_mzs:solar_beam", 70);
      mc.system.runTimeout(() => {
        player.setDynamicProperty("hf_mzs:using_ability", false);
        player.getComponent("movement").setCurrentValue(0.1);
      }, umvuthi.SOLAR_BEAM_LENGTH - umvuthi.SOLAR_BEAM_HIT_KF);
    }, umvuthi.SOLAR_BEAM_HIT_KF);
    return;
  }

  // Supernova
  if (player.getDynamicProperty("hf_mzs:can_supernova")) {
    player.setDynamicProperty("hf_mzs:can_supernova", false);
    player.setDynamicProperty("hf_mzs:sneaking_counter", 0);
    player.setDynamicProperty("hf_mzs:can_count_sneak", true);

    player.setDynamicProperty("hf_mzs:using_ability", true);
    player.runCommand("/fog @a push hf_mzs:supernova supernova");
    player.runCommand(`/titleraw @s actionbar {"rawtext":[{"translate":"actionbar.hf_mzs.suns_blessing_supernova"}]}`);
    playTpAnim(player, "animation.hf_mzs.suns_blessing.tp_supernova");

    player.runCommand("/inputpermission set @s movement disabled");
    player.runCommand("/inputpermission set @s camera disabled");

    //player.runCommand("/tp @s ~~~ ~ 0");
    player.getComponent("movement").setCurrentValue(0.05);

    if (player.getGameMode() !== "creative") {
      const newItem = event.itemStack.clone();
      newItem.setDynamicProperty("hf_mzs:was_used", true);
      newItem.getComponent("minecraft:durability").damage = 3599;
      player.getComponent("equippable").setEquipment("Mainhand", newItem);
    }

    mc.system.runTimeout(() => {
      player.runCommand("/summon hf_mzs:supernova_player");
      player.setDynamicProperty("hf_mzs:supernova", SUPERNOVA_DAMAGE_LENGTH);
      mc.system.runTimeout(() => {
        player.runCommand("/inputpermission set @s movement enabled");
        player.runCommand("/inputpermission set @s camera enabled");
        player.runCommand("/fog @a remove supernova");

        player.setDynamicProperty("hf_mzs:using_ability", false);
        player.getComponent("movement").setCurrentValue(0.1);
      }, SUPERNOVA_LENGTH - umvuthi.SUPERNOVA_HIT_KF);
    }, umvuthi.SUPERNOVA_HIT_KF);
    return;
  }
}

export function hitBlock(event) {
  const entity = event.damagingEntity;
  const item = entity.getComponent("equippable")?.getEquipment("Mainhand");
  if (
    !entity.getDynamicProperty("hf_mzs:can_supernova") &&
    item !== undefined &&
    item.typeId === "hf_mzs:suns_blessing" &&
    item.getComponent("minecraft:durability").damage < 3599
  ) {
    if (event.blockFace !== "Up") return;
    if (entity.getDynamicProperty("hf_mzs:sunstrike") > 0) return;
    const pos = vector.add(event.hitBlock.location, { x: 0.5, y: 1, z: 0.5 });
    if (
      entity.dimension.getBlockFromRay(pos, vector.up, {
        maxDistance: 200,
        includeLiquidBlocks: false,
        includePassableBlocks: false,
      })
    )
      return;
    if (entity.getGameMode() !== "creative") {
      const newItem = item.clone();
      newItem.setDynamicProperty("hf_mzs:was_used", true);
      entity.getComponent("equippable").setEquipment("Mainhand", newItem);
    }
    entity.setDynamicProperty("hf_mzs:sunstrike", 15);
    const sunstrike = entity.dimension.spawnEntity("hf_mzs:sunstrike", pos);
    sunstrike.setDynamicProperty("hf_mzs:caster_id", entity.id);
  }
}

export function tick100(player, hasSunsBlessing, itemSearch, container, i) {
  if (hasSunsBlessing) {
    const newItem = itemSearch.clone();
    player.dimension.spawnItem(newItem, vector.add(player.location, vector.multiply(player.getViewDirection(), 3)));
    container.setItem(i);
    player.runCommand('/tellraw @s {"rawtext":[{"translate":"message.hf_mzs.suns_blessing_dublicate"}]}');
    return;
  }
  if (player.getGameMode() === "creative") return;
  if (
    itemSearch.getComponent("minecraft:durability").damage >= 3599 ||
    !itemSearch.getDynamicProperty("hf_mzs:was_used")
  )
    return;
  //mc.world.sendMessage("Sun's blessing")
  hasSunsBlessing = true;
  const newItem = itemSearch.clone();
  newItem.getComponent("minecraft:durability").damage = Math.min(
    itemSearch.getComponent("minecraft:durability").damage + 5,
    3599
  );
  container.setItem(i, newItem);
}

export function tick5(player) {
  supernovaTick(player);
  solarBeamTick(player);
  if (player.getDynamicProperty("hf_mzs:sunstrike") > 0)
    player.setDynamicProperty("hf_mzs:sunstrike", player.getDynamicProperty("hf_mzs:sunstrike") - 5);
}

export function tick1(player) {
  sneakDetection(player);

  const solarBeamTime = player.getDynamicProperty("hf_mzs:solar_beam");
  if (solarBeamTime <= 0) {
    return;
  }
  const dir = player.getViewDirection();
  const rot_x = 90 + -(Math.acos(dir.y / vector.magnitude(dir)) * 180) / Math.PI;
  const rot_y = -(Math.atan2(dir.x, dir.z) * 180) / Math.PI;

  const sneakingOffset = player.isSneaking ? -0.25 : 0;
  let particlePos = vector.add(player.location, vector.multiply(player.getViewDirection(), 0.7));
  particlePos.y += sneakingOffset;
  const effect = player.dimension.spawnEntity("hf_mzs:sun_beam_player", particlePos);

  effect.setProperty("hf_mzs:x_rot", rot_x);
  effect.setProperty("hf_mzs:y_rot", rot_y);

  const pointingBlock = player.dimension.getBlockFromRay(
    vector.add(player.location, { x: 0, y: 0.94 + sneakingOffset, z: 0 }),
    player.getViewDirection(),
    {
      maxDistance: 20,
      includeLiquidBlocks: false,
      includePassableBlocks: false,
    }
  );
  if (pointingBlock !== undefined) {
    //mc.world.sendMessage(`${vector.string(pointingBlock.block.location)}`)
    const pos = vector.subtract(vector.add(pointingBlock.block.location, pointingBlock.faceLocation), dir);
    player.runCommand(`/particle hf_mzs:sun_beam_circle_big ${vector.string(pos)}`);
    player.runCommand(`/particle minecraft:lava_particle ${vector.string(pos)}`);
  }
}

function sneakDetection(player) {
  if (player.getDynamicProperty("hf_mzs:using_ability") === true) return;

  const equippable = player.getComponent("equippable").getEquipment("Mainhand");
  if (player.getDynamicProperty("hf_mzs:can_supernova") && equippable?.typeId !== "hf_mzs:suns_blessing") {
    cancelSupernova(player);
    return;
  }
  if (equippable?.typeId !== "hf_mzs:suns_blessing") {
    return;
  }
  if (
    player.isSneaking &&
    equippable.typeId === "hf_mzs:suns_blessing" &&
    equippable.getComponent("minecraft:durability").damage >= 3599
  ) {
    player.runCommand(
      `/titleraw @s actionbar {"rawtext":[{"translate":"actionbar.hf_mzs.suns_blessing_supernova_fail"}]}`
    );
    return;
  }

  player.setDynamicProperty(
    "hf_mzs:sneaking_counter",
    Math.max(player.getDynamicProperty("hf_mzs:sneaking_counter") - 1, 0)
  );

  // on sneak
  if (
    !player.getDynamicProperty("hf_mzs:can_supernova") &&
    player.isSneaking &&
    player.getDynamicProperty("hf_mzs:can_count_sneak")
  ) {
    if (player.getDynamicProperty("hf_mzs:sneaking_counter") < 12) {
      player.runCommand(
        `/titleraw @s actionbar {"rawtext":[{"translate":"actionbar.hf_mzs.suns_blessing_supernova_count1"}]}`
      );
      player.setDynamicProperty("hf_mzs:sneaking_counter", 23);
    } else if (player.getDynamicProperty("hf_mzs:sneaking_counter") < 24) {
      player.runCommand(
        `/titleraw @s actionbar {"rawtext":[{"translate":"actionbar.hf_mzs.suns_blessing_supernova_count2"}]}`
      );
      player.setDynamicProperty("hf_mzs:sneaking_counter", 35);
    } else if (player.getDynamicProperty("hf_mzs:sneaking_counter") < 36) {
      player.setDynamicProperty("hf_mzs:sneaking_counter", 50);
    }
    player.setDynamicProperty("hf_mzs:can_count_sneak", false);
  }
  // on unsneak
  else if (
    !player.getDynamicProperty("hf_mzs:can_supernova") &&
    !player.isSneaking &&
    !player.getDynamicProperty("hf_mzs:can_count_sneak")
  ) {
    player.setDynamicProperty("hf_mzs:can_count_sneak", true);
  }

  if (
    !player.getDynamicProperty("hf_mzs:can_supernova") &&
    player.getDynamicProperty("hf_mzs:sneaking_counter") >= 36
  ) {
    player.setDynamicProperty("hf_mzs:can_supernova", true);
    player.runCommand(
      `/titleraw @s actionbar {"rawtext":[{"translate":"actionbar.hf_mzs.suns_blessing_supernova_ready"}]}`
    );
  }

  // cancel cast on jump
  if (player.getDynamicProperty("hf_mzs:can_supernova") && player.isJumping) {
    cancelSupernova(player);
  } else if (player.getDynamicProperty("hf_mzs:can_supernova") && !player.isJumping) {
    player.getComponent("movement").setCurrentValue(0.05);
  }
}

function cancelSupernova(player) {
  player.setDynamicProperty("hf_mzs:can_supernova", false);
  player.setDynamicProperty("hf_mzs:sneaking_counter", 0);
  player.setDynamicProperty("hf_mzs:can_count_sneak", true);
  player.runCommand(
    `/titleraw @s actionbar {"rawtext":[{"translate":"actionbar.hf_mzs.suns_blessing_supernova_cancel"}]}`
  );
  player.getComponent("movement").setCurrentValue(0.1);
}

function supernovaTick(player) {
  const supernovaTime = player.getDynamicProperty("hf_mzs:supernova");
  if (supernovaTime <= 0) {
    return;
  }
  //mc.world.sendMessage(`${player.getComponent('movement').currentValue}`);
  player.runCommand("/execute as @s rotated ~ 0 run tp @e[type=hf_mzs:supernova_player,c=1,r=4] ^^^1.6");
  //player.teleport(player.location);
  // Pulls everything in within its range
  if (supernovaTime >= SUPERNOVA_DAMAGE_LENGTH - umvuthi.SUPERNOVA_PAUSE_KF) {
    player.addEffect("levitation", 35, {
      amplifier: 0,
      showParticles: false,
    });

    const entities = selectors.union(
      {
        location: player.location,
        maxDistance: umvuthi.SUPERNOVA_PULL_DIST,
        excludeFamilies: ["inanimate"],
      },
      ["mob", "player"],
      player.dimension,
      player.id
    );
    for (let i = 0; i < entities.length; i++) {
      if (!entities[i].isValid) continue;
      const dir = vector.subtract(vector.add(player.location, vector.multiply(vector.up, 3)), entities[i].location);
      entities[i].applyKnockback(dir.x, dir.z, 1.1, 0.4);
    }
    //mc.world.sendMessage('pull');
  }
  // After a short cooldown, it starts blasting away
  else if (supernovaTime < SUPERNOVA_DAMAGE_LENGTH - umvuthi.SUPERNOVA_PUSH_KF) {
    player.runCommand("/camerashake add @a[r=16] 0.5 0.3 positional");
    const entities = selectors.union(
      {
        location: player.location,
        maxDistance: umvuthi.SUPERNOVA_PUSH_DIST,
        excludeFamilies: ["inanimate"],
      },
      ["mob", "player"],
      player.dimension,
      player.id
    );
    for (let i = 0; i < entities.length; i++) {
      if (!entities[i].isValid) continue;
      const dir = vector.subtract(entities[i].location, player.location);
      entities[i].applyKnockback(dir.x, dir.z, umvuthi.SUPERNOVA_PUSH_KB, 0.5);
      entities[i].applyDamage(umvuthi.SUPERNOVA_DAMAGE, {
        cause: "entityAttack",
        damagingEntity: player,
      });
      entities[i].setOnFire(1.5);
    }
    //mc.world.sendMessage('boom');
  }
  player.setDynamicProperty("hf_mzs:supernova", supernovaTime - 5);
}

function solarBeamTick(player) {
  const solarBeamTime = player.getDynamicProperty("hf_mzs:solar_beam");
  if (solarBeamTime <= 0) {
    return;
  }
  const hitMobs = player.getEntitiesFromViewDirection({
    maxDistance: 20,
    families: ["mob"],
  });
  const hitPlayers = player.getEntitiesFromViewDirection({
    maxDistance: 20,
    families: ["player"],
  });
  const hit = hitMobs.concat(hitPlayers);

  for (let i = 0; i < hit.length; i++) {
    if (!hit[i].entity.isValid()) return;
    const dir = vector.subtract(hit[i].entity.location, player.location);
    hit[i].entity.applyKnockback(dir.x, dir.z, 1, 0.2);
    hit[i].entity.applyDamage(umvuthi.SOLAR_BEAM_DAMAGE, {
      cause: "entityAttack",
      damagingEntity: player,
    });
    hit[i].entity.setOnFire(umvuthi.SOLAR_BEAM_FIRE_TIME);
  }
  player.setDynamicProperty("hf_mzs:solar_beam", solarBeamTime - 5);
}
