import * as mc from "@minecraft/server";
import * as effects from "./effects";
import * as entityUtils from "./utils/entityUtils";
import * as selectors from "./utils/selectors";
import * as vector from "./utils/vector";

import { umvuthanaMaskEffects, umvuthanaBeforeUse } from "./items/umvuthanaMask";
import * as sunsBlessing from "./items/sunsBlessing";
import { foodFinishUse } from "./items/food";
import { openGuidebook } from "./items/guidebook";
import { addLore } from "./items/lore";

import * as earthrend from "./items/earthrendGauntlet";
import * as geomancy from "./items/geomancerArmor";
import * as staff from "./items/sculptorStaff";

import {
  umvuthanaTargetTimePass,
  markUmvuthanaTarget,
  onHitBlockUmvuthana,
  onBreakBlockUmvuthana,
} from "./misc/umvuthanaTargetBehavior";

export function useOnBlock(event) {
  if (event.itemStack.typeId !== "hf_mzs:captured_grottol_mixed") return;
  const pos = vector.add(event.block.location, event.faceLocation);
  const grottol = event.source.dimension.spawnEntity("hf_mzs:grottol", pos);
  grottol.setProperty("hf_mzs:deepslate", true);
  //grottol.triggerEvent("minecraft:entity_spawned");

  for (let i = 1; i <= 7; i++) {
    grottol.setProperty(`hf_mzs:pink${i}`, event.itemStack.getDynamicProperty(`hf_mzs:pink${i}`));
  }
}
export function hitBehavior(event) {
  if (!event.hitEntity.isValid() || event.damagingEntity.typeId !== "minecraft:player") return;

  // UMVUTHANA HIT AGRO
  if (
    event.hitEntity.hasComponent("type_family") &&
    event.hitEntity.getComponent("type_family").hasTypeFamily("hf_mzs_umvuthana") &&
    !event.hitEntity.getProperty("hf_mzs:tamed")
  )
    markUmvuthanaTarget(event.damagingEntity);

  const item = event.damagingEntity.getComponent("equippable").getEquipment("Mainhand");
  if (item === undefined) return;
  if (item.typeId === "hf_mzs:wroughtnaut_axe") {
    event.hitEntity.runCommand("/playsound random.anvil_land @a[r=16] ~~~ 1 0.5");
  }
  if (item.typeId === "hf_mzs:naga_fang_dagger") {
    const hitAngle = Math.atan2(event.hitEntity.getViewDirection().x, event.hitEntity.getViewDirection().z);
    const playerAngle = Math.atan2(
      event.damagingEntity.getViewDirection().x,
      event.damagingEntity.getViewDirection().z
    );

    if (Math.abs(hitAngle - playerAngle) > (Math.PI * 2) / 3) return;

    event.damagingEntity.playAnimation("animation.hf_mzs.naga_fang_dagger.tp_attack", {
      stopExpression: "v.is_first_person || !q.is_item_name_any('slot.weapon.mainhand', 'hf_mzs:naga_fang_dagger')",
    });
    // event.damagingEntity.playAnimation("animation.hf_mzs.naga_fang_dagger.fp_attack", { stopExpression: "!v.is_first_person" });
    event.hitEntity.applyDamage(3, {
      cause: "entityAttack",
      damagingEntity: event.damagingEntity,
    });
    event.hitEntity.addEffect("poison", 40, {
      amplifier: 1,
      showParticles: true,
    });
    event.hitEntity.runCommand("/playsound hf_mzs:misc.acid_hit @a[r=16] ~~~ 1 1");
    event.hitEntity.runCommand("/particle hf_mzs:dagger1 ~~1~");
    event.hitEntity.runCommand("/particle hf_mzs:dagger2 ~~1~");
    return;
  }
  if (item.typeId === "hf_mzs:spear") {
    if (Math.random() > 0.33) return;
    const family = event.hitEntity.getComponent("minecraft:type_family");
    if (!(family.hasTypeFamily("mob") && !family.hasTypeFamily("monster"))) return;

    event.hitEntity.applyDamage(100, {
      cause: "entityAttack",
      damagingEntity: event.damagingEntity,
    });
  }
}

export function finishUse(event) {
  if (event.itemStack === undefined) return;
  foodFinishUse(event);
}

export function beforeUse(event) {
  if (event.itemStack === undefined) return;
  if (
    (event.itemStack.typeId === "hf_mzs:ice_crystal" || event.itemStack.typeId === "hf_mzs:suns_blessing") &&
    event.itemStack.getComponent("minecraft:durability").damage ==
      event.itemStack.getComponent("minecraft:durability").maxDurability
  )
    event.cancel = true;
  earthrend.startUsing(event);
  staff.using(event);
  umvuthanaBeforeUse(event);
}

export function hitBlock(event) {
  onHitBlockUmvuthana(event);
  sunsBlessing.hitBlock(event);
}

export function breakBlock(event) {
  onBreakBlockUmvuthana(event);
}

export function startUse(event) {
  if (event.itemStack === undefined) return;
  event.source.addTag("hf_mzs_using");
  if (event.itemStack.typeId === "hf_mzs:ice_crystal" && !event.source.hasTag("hf_mzs_breath_sound")) {
    //mc.world.sendMessage("breath 1");
    event.source.runCommand("/playsound hf_mzs:misc.ice_breath @s");
    event.source.addTag("hf_mzs_breath_sound");
  }

  if (event.itemStack.typeId === "hf_mzs:wroughtnaut_axe" && !event.source.isSneaking) wroughtnautAxeSwing(event);
  if (event.itemStack.typeId === "hf_mzs:wroughtnaut_axe" && event.source.isSneaking) wroughtnautAxeSlam(event);
  if (event.itemStack.typeId === "hf_mzs:suns_blessing") sunsBlessing.use(event);
  if (event.itemStack.typeId === "hf_mzs:guidebook") openGuidebook(event);
}

export function stopUse(event) {
  earthrend.stopUsing(event);
  event.source.removeTag("hf_mzs_using");

  if (event.itemStack === undefined) return;
  if (event.itemStack.typeId === "hf_mzs:ice_crystal") {
    mc.system.runTimeout(() => {
      if (!event.source.hasTag("hf_mzs_using")) {
        event.source.removeTag("hf_mzs_breath_sound");
        event.source.runCommand("/stopsound @s hf_mzs:misc.ice_breath");
      }
    }, 5);
  }
}

export function tick1(players) {
  for (let iterant = 0; iterant < players.length; iterant++) {
    if (!players[iterant].isValid()) continue;
    if (players[iterant].getDynamicProperty("hf_mzs:jumping") > 0)
      players[iterant].setDynamicProperty("hf_mzs:jumping", players[iterant].getDynamicProperty("hf_mzs:jumping") - 1);
    if (players[iterant].isJumping) players[iterant].setDynamicProperty("hf_mzs:jumping", 10);

    sunsBlessing.tick1(players[iterant]);

    // thatch break fall
    const bAir = players[iterant].dimension.getBlockFromRay(players[iterant].location, vector.down, {
      maxDistance: 1,
    });
    const bThatch = players[iterant].dimension.getBlockFromRay(players[iterant].location, vector.down, {
      maxDistance: 4,
    });
    if (bAir === undefined && bThatch !== undefined && bThatch.block.typeId === "hf_mzs:thatch") {
      //mc.world.sendMessage("fall");
      players[iterant].addEffect("resistance", 3, {
        amplifier: 3,
        showParticles: false,
      });
    }
  }
}

export function tick5(players) {
  for (let iterant = 0; iterant < players.length; iterant++) {
    const player = players[iterant];
    if (!player.isValid()) continue;
    iceCrystal(player);
    sunsBlessing.tick5(player);
  }
}

export function tick20(players) {
  for (let i = 0; i < players.length; i++) {
    const player = players[i];
    if (!player.isValid()) return;
    umvuthanaMaskEffects(player);
    umvuthanaTargetTimePass(player);
    const inventory = player.getComponent("inventory");
    if (!inventory || !inventory.container) return;
    const { container } = inventory;
    for (let i = 0; i <= inventory.inventorySize - 1; i++) {
      const itemSearch = container.getItem(i);
      if (itemSearch === undefined) continue;
      addLore(container, i, itemSearch);
    }
  }
}

export function tick100(players) {
  for (let iterant = 0; iterant < players.length; iterant++) {
    const player = players[iterant];
    if (!player.isValid() || player.hasTag("hf_mzs_using")) continue;
    const inventory = player.getComponent("inventory");
    if (!inventory || !inventory.container) return;
    const { container } = inventory;

    let hasSunsBlessing = false;
    for (let i = 0; i <= inventory.inventorySize - 1; i++) {
      const itemSearch = container.getItem(i);
      if (itemSearch === undefined) continue;

      if (itemSearch.typeId === "hf_mzs:ice_crystal" && itemSearch.getComponent("minecraft:durability").damage > 0) {
        const newItem = itemSearch.clone();
        newItem.getComponent("minecraft:durability").damage = Math.max(
          newItem.getComponent("minecraft:durability").damage - 8,
          0
        );
        container.setItem(i, newItem);
      }

      if (player.getDynamicProperty("hf_mzs:using_ability") === false && itemSearch.typeId === "hf_mzs:suns_blessing") {
        sunsBlessing.tick100(player, hasSunsBlessing, itemSearch, container, i);
        hasSunsBlessing = true;
      }
    }
  }
}

function iceCrystal(player) {
  if (!player.hasTag("hf_mzs_using")) return;
  const item = player.getComponent("equippable").getEquipment("Mainhand");
  if (item && item.typeId !== "hf_mzs:ice_crystal") return;

  const damage =
    player.getGameMode() !== "creative" && player.getGameMode() !== "spectator"
      ? item.getComponent("enchantable").hasEnchantment("unbreaking")
        ? (4 - item.getComponent("enchantable").getEnchantment("unbreaking").level) / 4 > Math.random()
          ? 1
          : 0
        : 1
      : 0;
  var newItem = item.clone();
  newItem.getComponent("minecraft:durability").damage = Math.min(
    newItem.getComponent("minecraft:durability").damage + damage,
    newItem.getComponent("minecraft:durability").maxDurability
  );
  player.getComponent("equippable").setEquipment("Mainhand", newItem);

  const dir = player.getViewDirection();

  const rot_x = 90 + (-1 * (Math.acos(dir.y / vector.magnitude(dir)) * 180)) / Math.PI;
  const rot_y = (-1 * (Math.atan2(dir.x, dir.z) * 180)) / Math.PI;

  //mc.world.sendMessage(rot_x + '   ' + rot_y)

  const effect = player.dimension.spawnEntity("hf_mzs:ice_crystal_particle", player.location);
  //effect.setRotation(player.getRotation());
  effect.setProperty("hf_mzs:x_rot", rot_x);
  effect.setProperty("hf_mzs:y_rot", rot_y);

  entityUtils.freezeWater(player);
  const arc = selectors.getEntitiesArc(player, ["mob", "player"], 14, 45);

  for (let i = 0; i < arc.length; i++) {
    if (arc[i] === undefined || effects.checkIfImmuneToFreezing(arc[i].typeId)) continue;
    arc[i].applyDamage(1, {
      cause: "freezing",
      damagingEntity: player,
    });
    effects.applyColdEffect(arc[i], 1);
    arc[i].teleport(arc[i].location);
  }
}

function wroughtnautAxeSwing(event) {
  event.source.playAnimation("animation.hf_mzs.wroughtnaut_axe.tp_swing", {
    stopExpression: "v.is_first_person || !q.is_item_name_any('slot.weapon.mainhand', 'hf_mzs:wroughtnaut_axe')",
  });
  mc.system.runTimeout(() => {
    event.source.runCommand("/playsound hf_mzs:misc.whoosh @a[r=16] ~~~ 1 1");
  }, 6);
  mc.system.runTimeout(() => {
    const item = event.source.getComponent("equippable").getEquipment("Mainhand");
    if (item.typeId !== "hf_mzs:wroughtnaut_axe") return;
    const arc = selectors.getEntitiesArc(event.source, ["mob", "player"], 5, 100);
    const r = event.source.getViewDirection();

    let playedSound = false;
    for (var i = 0; i < arc.length; i++) {
      if (arc[i] === undefined || entityUtils.breakShield(arc[i])) continue;
      if (!playedSound) {
        playedSound = true;
        event.source.runCommand("/playsound random.anvil_land @a[r=16] ~~~ 1 0.5");
      }
      arc[i].applyKnockback(r.x, r.z, 2.5, 0.1);
      arc[i].applyDamage(7, {
        cause: "entityAttack",
        damagingEntity: event.source,
      });
    }
  }, 12);
}

function wroughtnautAxeSlam(event) {
  event.source.playAnimation("animation.hf_mzs.wroughtnaut_axe.tp_slam", {
    stopExpression: "v.is_first_person || !q.is_item_name_any('slot.weapon.mainhand', 'hf_mzs:wroughtnaut_axe')",
  });

  mc.system.runTimeout(() => {
    event.source.runCommand("/playsound hf_mzs:misc.whoosh @a[r=16] ~~~ 1 1");
  }, 6);
  mc.system.runTimeout(() => {
    const item = event.source.getComponent("equippable").getEquipment("Mainhand");
    if (item.typeId !== "hf_mzs:wroughtnaut_axe") return;
    event.source.runCommand("/playsound random.anvil_land @a[r=16] ~~~ 1 0.5");
    event.source.runCommand("/playsound random.explode @a[r=16] ~~~ 0.7 1");
    event.source.runCommand("/camerashake add @a[r=16] 0.3 0.5 positional");
    for (let i = 0; i < 10; i++) {
      const block = event.source.dimension.getBlockFromRay(
        vector.add(
          vector.add(event.source.location, vector.multiply(vector.flatten(event.source.getViewDirection(), "y"), i)),
          vector.up
        ),
        vector.down,
        {
          maxDistance: 2,
          includePassableBlocks: false,
          includeLiquidBlocks: false,
        }
      );
      if (block === undefined) continue;

      let map = new mc.MolangVariableMap();
      map.setFloat("variable.radius", i / 5);
      event.source.dimension.spawnParticle(
        "hf_mzs:wroughtnaut_attack_slam_player",
        vector.add(vector.up, block.block.location),
        map
      );
      //event.source.runCommand(`/particle hf_mzs:wroughtnaut_attack_slam ${vector.string(vector.add(vector.up, block.block.location))}`);
    }

    const arc = selectors.getEntitiesArc(event.source, ["mob", "player"], 10, 40);

    for (var i = 0; i < arc.length; i++) {
      if (arc[i] === undefined || entityUtils.breakShield(arc[i])) continue;
      const r = vector.flatten(vector.subtract(arc[i].location, event.source.location), "y");
      arc[i].applyKnockback(-r.x, -r.z, 5, 1.1);
      arc[i].applyDamage(9, {
        cause: "entityAttack",
        damagingEntity: event.source,
      });
    }
  }, 14);
}

export function playTpAnim(source, animation) {
  source.runCommand(`/playanimation @s ${animation} d 0.0 \"v.is_first_person\"`);
}
