/*
hello dear add-on maker. want to use my code? sure. but it would probably help if you understand how it works instead of
just copy pasting it and changing ids...

the code shouldnt be too hard to understand. should be easy to configure for your own things

but if you're mostly just using the same code, would be nice if you credit

otherwise, have fun removing hit immunity :)

- JuliusScizzor
*/


import {
    GameMode,
    world,
    Vector,
    Player,
    system,
    EntityDamageCause,
    EntityEquipmentInventoryComponent,
    EquipmentSlot,
    ItemStack,
    ItemEnchantsComponent,
    EnchantmentTypes,
    ItemDurabilityComponent,
    EntityHealthComponent,
    Entity,
  } from "@minecraft/server";
  
import './functions';
import './customProjectileDamage';
import './customDeathMessage';


world.afterEvents.entityHurt.subscribe(({ hurtEntity, damageSource }) => {
  if (damageSource.cause == "entityExplosion") {
    hurtEntity.triggerEvent("js:stunned")
  }
},
{ entityTypes: ["js:scp682"] })

world.beforeEvents.chatSend.subscribe((ev) => {
  let { sender, message } = ev;
  if (!message.startsWith('!')) return;

  ev.cancel = true;

  const command = message.substring(1);
  if (!(command in commands)) {
    sender.sendMessage(`§c${command} is not a valid command`)
    return;
  }

  const { command: commandToRun, notification } = commands[command];
  sender.runCommandAsync(commandToRun);
  /*
  for (const p of world.getPlayers()) {
    if (!p.isOp()) continue;
    p.sendMessage([
      { text: `§o§7[${sender.name}: ` },
      { translate: notification },
      { text: ']' },
    ]);
  }
  */
});


const commands = {
  "leave": {
    command: "function spectate/leaveSpectate",
  },
};



function playerSystem(player) {
  if (player.hasTag("doubleJump")) {
    const directionX = player.getViewDirection().x;
    const directionZ = player.getViewDirection().z;
    player.applyKnockback(directionX, directionZ, 0.06, 0.6);
    player.removeTag("doubleJump");
  }

  if (player.hasTag("boostPad")) {
    const directionX = player.getViewDirection().x;
    const directionZ = player.getViewDirection().z;
    player.applyKnockback(directionX, directionZ, 0.5, 1.5);
    player.playSound('mob.enderdragon.flap')
    player.removeTag("boostPad");
  }

  if (player.hasTag("boostPad2")) {
    const directionX = player.getViewDirection().x;
    const directionZ = player.getViewDirection().z;
    player.applyKnockback(directionX, directionZ, 1, 1.5);
    player.playSound('mob.enderdragon.flap')
    player.removeTag("boostPad2");
  }

  if (player.hasTag("dash")) {
    const directionX = player.getVelocity().x;
    const directionZ = player.getVelocity().z;
    if (player.isOnGround) {
      player.applyKnockback(directionX, directionZ, 5, 0);
    } else {
      player.applyKnockback(directionX, directionZ, 2, 0);
    }
    player.removeTag("dash");
  }
  if (player.hasTag("ngl7Knockback")) {
    const directionX = player.getViewDirection().x;
    const directionZ = player.getViewDirection().z;

    player.applyKnockback(directionX, directionZ, -2, 0.1);
    player.removeTag("ngl7Knockback");
  }
  if (player.hasTag("crusherVelocity")) {
    const directionX = player.getViewDirection().x;
    const directionZ = player.getViewDirection().z;

    player.applyKnockback(directionX, directionZ, 2, 0);
    player.removeTag("crusherVelocity");
  }
}

system.run(function playerTick(ev) {
  system.run(playerTick);
  for (let plr of world.getPlayers()) {
    playerSystem(plr);
  }
  
  for (let ent of world.getDimension("overworld").getEntities()) {
    if (ent.hasTag("clearVelocity")) {
      ent.clearVelocity()
      ent.removeTag("clearVelocity");
    }
    if (ent.hasTag("smashVelocity")) {
      const directionX = ent.getViewDirection().x;
      const directionY = ent.getViewDirection().y;
      const directionZ = ent.getViewDirection().z;
  
      ent.applyImpulse({x : directionX * 2, y: 0.55, z: directionZ * 2})
      ent.removeTag("smashVelocity");
    }
    if (ent.typeId == "js:scp682") {
      const health = (ent.getComponent("health"));
      const healthRounded = Math.floor(health.currentValue)
      ent.runCommandAsync(`scoreboard players set @a health ${healthRounded}`)
    } 
  }
})




system.afterEvents.scriptEventReceive.subscribe(event => {
  const entity = event.sourceEntity
  if (event.id == "js:hp_pickup") {
    healthPowerup(entity);
  }
})


function setSlotToAir(player, slot) {
  if (slot < 9) {
    player.runCommandAsync(`replaceitem entity @s slot.hotbar ${slot} air`);
  } else player.runCommandAsync(`replaceitem entity @s slot.inventory ${slot - 9} air`);
}

function itemQuery(player, itemIds) {
  const comp = player.getComponent("inventory");
  const inv = comp.container;
  let amount = 0;
  let info = [];
  for (let i = 0; i < inv.size; i++) {
    const item = inv.getItem(i);
    if (!item) continue;

    const { typeId, amount: iAmount, data } = item;
    if (itemIds.includes(typeId.replace("minecraft:", ""))) {
      amount += iAmount;
      info.push({
        slot: i,
        item: { typeId, amount: iAmount, data },
      });
    }
  }
  return {
    amount,
    slots: info,
  };
}

function healthPowerup(player) {
  const hp = player.getComponent("health");
  if (hp.currentValue <= 0) return;
  const itemInfo = itemQuery(player, ["js:health"]);
  if (itemInfo.amount <= 0) return;
  for (let slot of itemInfo.slots) setSlotToAir(player, slot.slot);

  hp.setCurrentValue(hp.currentValue + (itemInfo.amount * 2));
  player.playSound("misc.hp_pickup");
} 
