import { ContainerSlot, EntityProjectileComponent, Player } from "@minecraft/server";
import * as mc from "@minecraft/server";
import * as GMath from "../utils/GMath";
//Extras
var temporaryTags = {};
var soundsPlaying = {};
/**
 *
 * @param {mc.Player} player
 * @param {*} soundName
 * @param {number} volume
 * @param {number} duration
 */
function playSound(player, soundName, volume = 1, duration = 20) {
  if (!soundsPlaying[player.id]) {
    soundsPlaying[player.id] = {};
  }
  if (!soundsPlaying[player.id][soundName]) {
    soundsPlaying[player.id][soundName] = true;
    player.playSound(soundName, { volume: volume });
    mc.system.runTimeout(() => {
      delete soundsPlaying[player.id][soundName];
    }, duration);
  }
}
/**
 *
 * @param {mc.Player} player
 * @param {*} soundName
 * @param {number} volume
 * @param {number} duration
 */
function stopSound(player, soundName) {
  if (!soundsPlaying[player.id]) {
    soundsPlaying[player.id] = {};
  }
  if (soundsPlaying[player.id][soundName]) {
    delete soundsPlaying[player.id][soundName];
    player.runCommand(`stopsound @s ${soundName}`);
  }
}
function hasTag(player, tag) {
  if (
    temporaryTags[player.id] &&
    JSON.stringify(temporaryTags[player.id]).startsWith("[") &&
    temporaryTags[player.id].includes(tag)
  ) {
    return true;
  }
  return false;
}
function addTag(player, tag) {
  if (!temporaryTags[player.id]) {
    temporaryTags[player.id] = [];
  }
  if (temporaryTags[player.id].includes(tag) == false) {
    temporaryTags[player.id].push(tag);
  }
}
function removeTag(player, tag) {
  if (!temporaryTags[player.id]) {
    temporaryTags[player.id] = [];
  }
  temporaryTags[player.id] = temporaryTags[player.id].filter((e) => e != tag);
}
//Export
export default {
  "snst_bckp:ender_dragon_backpack": {
    durationCooldown: 20 * 20,
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const viewDirection = new GMath.Vector3(2, 2, 2).multiply(player.getViewDirection());
      const item = slot.getItem();
      if (item.getComponent("cooldown").getCooldownTicksRemaining(player) > 0) {
        const ticks = item.getComponent("cooldown").getCooldownTicksRemaining(player);
        player.onScreenDisplay.setActionBar({
          rawtext: [
            { translate: "ui.snst_bckp.backpack_cooldown", with: [`${Math.round(ticks / 20)}`] },
          ],
        });
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onSneaking(player, slot) {
      const viewDirection = new GMath.Vector3(2, 2, 2).multiply(player.getViewDirection());
      const item = slot.getItem();
      if (item.getComponent("cooldown").getCooldownTicksRemaining(player) == 0) {
        player.startItemCooldown(
          item.getComponent("cooldown").cooldownCategory,
          this.durationCooldown
        );
        const fireball = player.dimension.spawnEntity(
          "snst_bckp:dragon_fireball",
          new GMath.Vector3(player.getHeadLocation()).add(viewDirection)
        );
        /**@type {EntityProjectileComponent} */
        const projectile = fireball.getComponent("projectile");
        projectile.owner = player;
        projectile.shoot(viewDirection);
        player.dimension.playSound("mob.enderdragon.growl", player.location, {
          pitch: 2,
          volume: 0.2,
        });
      }
    },
  },
  "snst_bckp:wither_backpack": {
    durationCooldown: 20 * 20,
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const viewDirection = new GMath.Vector3(2, 2, 2).multiply(player.getViewDirection());
      const item = slot.getItem();
      if (item.getComponent("cooldown").getCooldownTicksRemaining(player) > 0) {
        const ticks = item.getComponent("cooldown").getCooldownTicksRemaining(player);
        player.onScreenDisplay.setActionBar({
          rawtext: [
            { translate: "ui.snst_bckp.backpack_cooldown", with: [`${Math.round(ticks / 20)}`] },
          ],
        });
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onSneaking(player, slot) {
      const viewDirection = new GMath.Vector3(2, 2, 2).multiply(player.getViewDirection());
      const item = slot.getItem();
      if (item.getComponent("cooldown").getCooldownTicksRemaining(player) == 0) {
        player.startItemCooldown(
          item.getComponent("cooldown").cooldownCategory,
          this.durationCooldown
        );
        const fireball = player.dimension.spawnEntity(
          "snst_bckp:wither_skull_dangerous",
          new GMath.Vector3(player.getHeadLocation()).add(viewDirection)
        );
        /**@type {EntityProjectileComponent} */
        const projectile = fireball.getComponent("projectile");
        fireball.setProperty("snst_bckp:rot_y", player.getRotation().y);
        fireball.setProperty("snst_bckp:rot_x", player.getRotation().x);
        player.playSound("mob.wither.shoot", { volume: 0.5 });
        projectile.owner = player;
        projectile.shoot(viewDirection);
      }
    },
  },
  "snst_bckp:enderman_backpack": {
    durationCooldown: 20 * 20,
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const item = slot.getItem();
      if (item.getComponent("cooldown").getCooldownTicksRemaining(player) > 0) {
        const ticks = item.getComponent("cooldown").getCooldownTicksRemaining(player);
        player.onScreenDisplay.setActionBar({
          rawtext: [
            { translate: "ui.snst_bckp.backpack_cooldown", with: [`${Math.round(ticks / 20)}`] },
          ],
        });
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onSneaking(player, slot) {
      const viewDirection = new GMath.Vector3(2, 2, 2).multiply(player.getViewDirection());
      const item = slot.getItem();
      if (item.getComponent("cooldown").getCooldownTicksRemaining(player) == 0) {
        player.startItemCooldown(
          item.getComponent("cooldown").cooldownCategory,
          this.durationCooldown
        );
        const fireball = player.dimension.spawnEntity(
          "snst_bckp:ender_pearl",
          new GMath.Vector3(player.getHeadLocation()).add(viewDirection)
        );
        /**@type {EntityProjectileComponent} */
        const projectile = fireball.getComponent("projectile");
        projectile.owner = player;
        projectile.shoot(viewDirection);
        player.playAnimation("animation.snst_bckp.player.shoot_item", {
          blendOutTime: 0.5,
        });
      }
    },
  },
  "snst_bckp:shark_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      ////console.warn("SWimg")
      player.runCommand(`effect @s water_breathing infinite 255 true`);
      //  player.addEffect("water_breathing", Infinity, {"showParticles": true, "amplifier": 255})
      if (player.isSwimming && player.isInWater) {
        player.getComponent("minecraft:underwater_movement").setCurrentValue(0.1);
      } else {
        player.getComponent("minecraft:underwater_movement").resetToDefaultValue();
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUnequip(player) {
      player.getComponent("minecraft:underwater_movement").resetToDefaultValue();
      player.removeEffect("water_breathing");
    },
  },
  "snst_bckp:axolotl_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      ////console.warn("SWimg")
      player.addEffect("water_breathing", 10, { showParticles: false, amplifier: 255 });
      //  player.addEffect("water_breathing", Infinity, {"showParticles": true, "amplifier": 255})
      if (player.isSwimming && player.isInWater) {
        player.getComponent("minecraft:underwater_movement").setCurrentValue(0.1);
      } else {
        player.getComponent("minecraft:underwater_movement").resetToDefaultValue();
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUnequip(player) {
      player.getComponent("minecraft:underwater_movement").resetToDefaultValue();
      player.removeEffect("water_breathing");
    },
  },
  "snst_bckp:slime_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      player.addEffect("jump_boost", 10, { showParticles: false, amplifier: 4 });
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onJump(player) {
      const blockDown = player.dimension.getBlockFromRay(
        player.location,
        new GMath.Vector3(0, -1, 0),
        { maxDistance: 1 }
      );
      if (
        blockDown &&
        !player.isOnGround &&
        player.isFalling == false &&
        player.isInWater == false
      ) {
        player.dimension.spawnParticle("snst_bckp:slime_jump", player.location);
        player.dimension.playSound("mob.slime.jump", player.location);
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUnequip(player) {
      player.removeEffect("jump_boost");
    },
  },
  "snst_bckp:creeper_backpack": {
    durationCooldown: 20 * 15,
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const viewDirection = new GMath.Vector3(2, 2, 2).multiply(player.getViewDirection());
      const item = slot.getItem();
      if (item.getComponent("cooldown").getCooldownTicksRemaining(player) > 0) {
        const ticks = item.getComponent("cooldown").getCooldownTicksRemaining(player);
        player.onScreenDisplay.setActionBar({
          rawtext: [
            { translate: "ui.snst_bckp.backpack_cooldown", with: [`${Math.round(ticks / 20)}`] },
          ],
        });
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */

    onJump(player, slot) {
      const item = slot.getItem();
      const cooldownComp = item.getComponent("cooldown");
      if (cooldownComp.getCooldownTicksRemaining(player) == 0 && player.isSneaking) {
        const tntEntity = player.dimension.spawnEntity("minecraft:tnt", player.getHeadLocation());
        const direction = new GMath.Vector3(1, 0, 1).multiply(player.getViewDirection());
        tntEntity.applyImpulse(direction.add(new GMath.Vector3(0, 1, 0)));
        player.startItemCooldown(cooldownComp.cooldownCategory, this.durationCooldown);
        player.playAnimation("animation.snst_bckp.player.tnt_shoot", {
          blendOutTime: 0.5,
        });
      }
    },
  },
  "snst_bckp:armadillo_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onSneaking(player, slot) {
      player.addEffect("resistance", 10, { showParticles: false, amplifier: 10 });
    },
  },
  "snst_bckp:guardian_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      player.addEffect("water_breathing", 10, { showParticles: false, amplifier: 255 });
    },
  },
  "snst_bckp:camera_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      player.addEffect("night_vision", 10, { showParticles: false, amplifier: 10 });
    },
  },
  "snst_bckp:buoy_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const inBlock = player.dimension.getBlock(player.location);
      if (player.isInWater && !player.isSwimming && !player.isJumping) {
        player.applyKnockback(0, 0, 0, 0.04);
        player.getComponent("minecraft:underwater_movement").setCurrentValue(0.1);
      } else {
        player.getComponent("minecraft:underwater_movement").resetToDefaultValue();
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUnequip(player) {
      player.getComponent("minecraft:underwater_movement").resetToDefaultValue();
    },
  },
  "snst_bckp:mimic_backpack": {
    durationCooldown: 20 * 3,
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const direction = new GMath.Vector2(0, 1).rotate(player.getRotation().y).normalize();
      const volumeBlock = new GMath.Vector3(0.6 * direction.x, 1, 0.6 * direction.y);
      const mobsBehind = player.dimension.getEntities({
        location: player.location,
        volume: volumeBlock,
        families: ["monster"],
        closest: 1,
      });
      const item = slot.getItem();
      const cooldownRemain = item.getComponent("cooldown").getCooldownTicksRemaining(player);
      if (mobsBehind.length > 0 && cooldownRemain == 0) {
        player.startItemCooldown(
          item.getComponent("cooldown").cooldownCategory,
          this.durationCooldown
        );
        mobsBehind.forEach((e) => {
          e.applyDamage(1, { damagingEntity: player, cause: mc.EntityDamageCause.entityAttack });
          player.playSound("mob.evocation_fangs.attack", { volume: 0.5, pitch: 1.2 });
        });
      } else if (cooldownRemain > 0) {
        player.onScreenDisplay.setActionBar({
          rawtext: [
            {
              translate: "ui.snst_bckp.backpack_cooldown",
              with: [`${Math.round(cooldownRemain / 20)}`],
            },
          ],
        });
      }
    },
  },
  "snst_bckp:iron_golem_backpack": {
    durationCooldown: 20 * 3,
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const direction = new GMath.Vector2(0, 1).rotate(player.getRotation().y).normalize();
      const volumeBlock = new GMath.Vector3(0.6 * direction.x, 1, 0.6 * direction.y);
      const mobsBehind = player.dimension.getEntities({
        location: player.location,
        volume: volumeBlock,
        families: ["monster"],
        closest: 1,
      });
      const item = slot.getItem();
      const cooldownRemain = item.getComponent("cooldown").getCooldownTicksRemaining(player);
      if (mobsBehind.length > 0 && cooldownRemain == 0) {
        player.startItemCooldown(
          item.getComponent("cooldown").cooldownCategory,
          this.durationCooldown
        );
        mobsBehind.forEach((e) => {
          e.applyDamage(1, { damagingEntity: player, cause: mc.EntityDamageCause.entityAttack });
          player.playSound("mob.irongolem.hit", { volume: 0.5 });
        });
      } else if (cooldownRemain > 0) {
        player.onScreenDisplay.setActionBar({
          rawtext: [
            {
              translate: "ui.snst_bckp.backpack_cooldown",
              with: [`${Math.round(cooldownRemain / 20)}`],
            },
          ],
        });
      }
    },
  },
  "snst_bckp:glow_squid_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const dimension = player.dimension;
      const currentBlock = dimension.getBlock(player.location);
      if (currentBlock.typeId == "minecraft:air") {
        player.addTag("snst_bckp:glowing");
        const blockData = {
          type: "light_block",
          owner: player.id,
        };
        mc.world.setDynamicProperty(
          `${dimension.id}:${currentBlock.x}:${currentBlock.y}:${currentBlock.z}`,
          JSON.stringify(blockData)
        );
        currentBlock.setType("snst_bckp:light_block");
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUnequip(player) {
      player.removeTag("snst_bckp:glowing");
    },
  },
  "snst_bckp:wings_backpack": {
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const item = slot.getItem();
      const cooldownComp = item.getComponent("cooldown");
      const cooldownRemain = cooldownComp.getCooldownTicksRemaining(player);
      if (cooldownRemain > 0) {
        player.onScreenDisplay.setActionBar({
          rawtext: [
            {
              translate: "ui.snst_bckp.backpack_cooldown",
              with: [`${Math.round(cooldownRemain / 20)}`],
            },
          ],
        });
      }
      var viewDirection = player.getViewDirection();
      if (player.isOnGround || player.isFlying) {
        if (player.hasTag("snst_bckp_flying")) {
          player.addTag("snst_bckp_wait_stop");
        }
        player.removeTag("snst_bckp_flying");
      }
      if (player.hasTag("snst_bckp_wait_stop")) {
        player.removeTag("snst_bckp_wait_stop");
        removeTag(player, "snst_bckp_playing_glide");
        player.removeEffect("slow_falling");
        stopSound(player, "elytra.loop");
        player.playAnimation("stop", {
          blendOutTime: 0.1,
          nextState: "sla",
          controller: "wings_backpack",
        });
        if (cooldownRemain == 0) {
          player.startItemCooldown(cooldownComp.cooldownCategory, 20 * 2);
        }
        player.camera.clear();
      }
      if (player.hasTag("snst_bckp_flying")) {
        if (player.isSneaking) {
          if (hasTag(player, "snst_bckp_playing_glide")) {
            player.camera.setCamera("minecraft:third_person");
            player.removeEffect("slow_falling");
            stopSound(player, "elytra.loop");
            player.playAnimation("animation.snst_bckp.player.stop_glide", {
              stopExpression:
                "q.is_on_ground || !q.is_sneaking || !q.is_item_name_any('slot.weapon.offhand', 'snst_bckp:wings_backpack')",
              blendOutTime: 0.1,
              nextState: "sla",
              controller: "wings_backpack",
            });
          }
          removeTag(player, "snst_bckp_playing_glide");
        } else {
          playSound(player, "elytra.loop", 0.5, 20 * 10);
          player.runCommand(`effect @s slow_falling infinite 255 true`);
          if (hasTag(player, "snst_bckp_playing_glide") == false) {
            player.camera.setCamera("minecraft:follow_orbit");
            addTag(player, "snst_bckp_playing_glide");
            player.playAnimation("animation.snst_bckp.player.gliding", {
              stopExpression:
                "q.is_on_ground || q.is_sneaking || !q.is_item_name_any('slot.weapon.offhand', 'snst_bckp:wings_backpack')",
              blendOutTime: 0.1,
              nextState: "sla",
              controller: "wings_backpack",
            });
            if (cooldownRemain == 0) {
              player.dimension.spawnParticle("snst_bckp:wind_burst", player.location);
              player.playSound("breeze_wind_charge.burst", { volume: 0.5, pitch: 0.5 });
              player.startItemCooldown(cooldownComp.cooldownCategory, 20 * 4);
              player.applyKnockback(viewDirection.x, viewDirection.z, 10, 4 * viewDirection.y);
            }
          } else {
            player.applyKnockback(viewDirection.x, viewDirection.z, 2, 1 * viewDirection.y);
          }
        }
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onJump(player, slot) {
      const item = slot.getItem();
      const cooldownComp = item.getComponent("cooldown");
      const cooldownRemain = cooldownComp.getCooldownTicksRemaining(player);
      if (cooldownRemain == 0) {
        if (player.isFalling && !player.isFlying && !player.hasTag("snst_bckp_flying")) {
          player.camera.setCamera("minecraft:follow_orbit");
          player.addTag("snst_bckp_flying");
        }
      }
    },
    onUnequip(player) {
      player.removeTag("snst_bckp_wait_stop");
      player.removeTag("snst_bckp_flying");
      removeTag(player, "snst_bckp_playing_glide");
      player.removeEffect("slow_falling");
      stopSound(player, "elytra.loop");
      player.camera.clear();
    },
  },
  "snst_bckp:shield_backpack": {
    durationCooldown: 20 * 1,
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const direction = new GMath.Vector2(0, 1).rotate(player.getRotation().y).normalize();
      const volumeBlock = new GMath.Vector3(0.7 * direction.x, 1, 0.7 * direction.y);
      let mobsBehind = player.dimension.getEntities({
        location: player.location,
        volume: volumeBlock,
      });
      const item = slot.getItem();
      const cooldownRemain = item.getComponent("cooldown").getCooldownTicksRemaining(player);
      mobsBehind = mobsBehind.filter(
        (e) => e.getComponent("projectile") && e.getComponent("projectile").owner.id != player.id
      );
      if (mobsBehind.length > 0 && cooldownRemain == 0) {
        player.startItemCooldown(
          item.getComponent("cooldown").cooldownCategory,
          this.durationCooldown
        );
        mobsBehind.forEach((e) => {
          player.playSound("item.shield.block", { volume: 0.5, pitch: 1.2 });
          e.clearVelocity();
        });
      } else if (cooldownRemain > 0) {
        player.onScreenDisplay.setActionBar({
          rawtext: [
            {
              translate: "ui.snst_bckp.backpack_cooldown",
              with: [`${Math.round(cooldownRemain / 20)}`],
            },
          ],
        });
      }
    },
  },
  "snst_bckp:samurai_backpack": {
    durationCooldown: 20 * 10,
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onUpdate(player, slot) {
      const item = slot.getItem();
      const cooldownComp = item.getComponent("cooldown");
      const cooldownRemain = cooldownComp.getCooldownTicksRemaining(player);
      if (cooldownRemain > 0) {
        player.onScreenDisplay.setActionBar({
          rawtext: [
            {
              translate: "ui.snst_bckp.backpack_cooldown",
              with: [`${Math.round(cooldownRemain / 20)}`],
            },
          ],
        });
      }
    },
    /**
     *
     * @param {Player} player
     * @param {ContainerSlot} slot
     */
    onSneaking(player, slot) {
      const item = slot.getItem();
      const cooldownComp = item.getComponent("cooldown");
      const cooldownRemain = cooldownComp.getCooldownTicksRemaining(player);
      let targets = player.dimension.getEntities({ location: player.location, maxDistance: 5 });
      targets = targets.filter((e) => e.id != player.id);
      if (cooldownRemain == 0) {
        player.dimension.spawnParticle("snst_bckp:smoke_fog", player.location);
        player.dimension.playSound("snst_bckp.item.smoke_fog.impact", player.location, {
          volume: 0.4,
        });
        player.addEffect("invisibility", 20 * 5, { showParticles: false });
        player.addEffect("speed", 20 * 5, { showParticles: false, amplifier: 2 });
        player.startItemCooldown(cooldownComp.cooldownCategory, this.durationCooldown);
        targets.forEach((e) =>
          e.addEffect("blindness", 20 * 2, { amplifier: 1, showParticles: false })
        );
      }
    },
  },
};
