import { EquipmentSlot, ItemStack } from "@minecraft/server";
import { afterEvents, beforeEvents, namespace as ns } from "./eternal/constants";
import { idTranslate, runInterval, runTimeout } from "./eternal/utils";

const allowedEntities = [`${ns}:ant`, `${ns}:butterfly`, `${ns}:firefly`, `${ns}:glass_jar.butterfly`, `${ns}:glass_jar.firefly`];

let useDelay = 0;

runInterval(() => {
  if (useDelay > 0) {
    useDelay--;
  }
});

afterEvents.itemUse.subscribe((e) => {
  const { source: player, itemStack } = e;
  if (itemStack && (itemStack.typeId === `${ns}:bug_net.empty` || itemStack.typeId === `${ns}:bug_net.full`)) {
    player.playAnimation(`animation.${ns}.player.bug_net.swing`, { stopExpression: "v.is_first_person" });
  }
});

beforeEvents.playerInteractWithEntity.subscribe((e) => {
  const { player, target, itemStack } = e;

  if (itemStack && itemStack.typeId === `${ns}:bug_net.empty` && allowedEntities.includes(target.typeId)) {
    runTimeout(() => {
      if (useDelay === 0) {
        catchEntity(player, target, itemStack);
        useDelay = 5;
      }
    });
  }
});

const bugNetComponent = {
  onMineBlock(e) {
    const { itemStack, source: player } = e;
    itemStack.durability--;
    player.setEquipment(EquipmentSlot.Mainhand, itemStack);
  },
  onHitEntity(e) {
    const { itemStack, attackingEntity: player, hitEntity } = e;
    if (itemStack.typeId === `${ns}:bug_net.empty`) {
      if (allowedEntities.includes(hitEntity.typeId)) {
        if (useDelay === 0) {
          player.playAnimation(`animation.${ns}.player.bug_net.swing`, { stopExpression: "q.is_first_person" });
          catchEntity(player, hitEntity, itemStack);
          useDelay = 5;
        }
      }
    } else {
      itemStack.durability--;
      player.setEquipment(EquipmentSlot.Mainhand, itemStack);
    }
  },
  onUseOn(e) {
    const { block, source: player, itemStack, faceLocation } = e;
    if (itemStack.typeId === `${ns}:bug_net.full`) {
      const location = {
        x: block.x + faceLocation.x + block.x,
        y: block.y + faceLocation.y + block.y,
        z: block.z + faceLocation.z + block.z,
      };

      const id = itemStack.getDynamicProperty(`${ns}:typeId`);

      if (useDelay === 0) {
        dropEntity(player, id, block.dimension, location);
        useDelay = 5;
      }
    }
  },
};

export function catchEntity(player, entity, itemStack) {
  const item = new ItemStack(`${ns}:bug_net.full`);
  if (itemStack.durability === 0) {
    player.setEquipment(EquipmentSlot.Mainhand, null);
    player.dimension.playSound("random.break", entity.location);
    return;
  }

  item.durability = itemStack.durability;
  if (player.gamemode !== "creative") item.durability--;

  storeBugData(item, entity);
  const name = idTranslate(entity.typeId);
  item.setLore(["§r§7This bug net contains:", `§i§8- ${name}§r`]);
  player.setEquipment(EquipmentSlot.Mainhand, item);

  player.dimension.playSound("armor.equip_leather", entity.location);
  entity.dispose();
}
export function dropEntity(player, id, dimension, location) {
  const entity = dimension.spawnEntity(id, location);
  const itemStack = player.getEquipment(EquipmentSlot.Mainhand);

  getBugData(entity, itemStack);

  const item = new ItemStack(`${ns}:bug_net.empty`);
  item.durability = itemStack.durability;

  if (item.durability === 0) {
    player.setEquipment(EquipmentSlot.Mainhand, null);
    player.dimension.playSound("random.break", entity.location);
  } else {
    player.setEquipment(EquipmentSlot.Mainhand, item);
    player.dimension.playSound("armor.equip_leather", entity.location);
  }
  return entity;
}

export function storeBugData(item, entity) {
  item.setDynamicProperty(`${ns}:typeId`, entity.typeId);
  item.setDynamicProperty(`${ns}:nameTag`, entity.nameTag);
  item.setDynamicProperty(`${ns}:health`, entity.health);
  const variant = entity.getProperty(`${ns}:variant`);
  if (variant !== undefined && variant !== null) {
    item.setDynamicProperty(`${ns}:variant`, variant);
  }
}

export function getBugData(entity, item) {
  entity.nameTag = item.getDynamicProperty(`${ns}:nameTag`);
  entity.health = item.getDynamicProperty(`${ns}:health`);

  const storedVariant = item.getDynamicProperty(`${ns}:variant`);
  if (storedVariant !== undefined && storedVariant !== null) {
    entity.setProperty(`${ns}:variant`, storedVariant);
  }
}

beforeEvents.worldInitialize.subscribe((e) => {
  const { itemComponentRegistry } = e;
  itemComponentRegistry.registerCustomComponent(`${ns}:bug_net`, bugNetComponent);
});
