import { world, system } from "@minecraft/server";

const mobAnimTypes = [
  "minecraft:cow",
  "minecraft:sheep",
  "minecraft:polar_bear",
  "minecraft:mooshroom",
  "minecraft:llama",
  "minecraft:horse",
  "minecraft:donkey",
  "minecraft:mule",
  "minecraft:skeleton_horse",
  "minecraft:zombie_horse",
  "minecraft:turtle",
  "minecraft:panda",
  "minecraft:creeper",
  "minecraft:enderman",
  "minecraft:skeleton",
  "minecraft:wither_skeleton",
  "minecraft:stray",
  "minecraft:slime",
  "minecraft:spider",
  "minecraft:zombie",
  "minecraft:zombie_pigman",
  "minecraft:husk",
  "minecraft:drowned",
  "minecraft:squid",
  "minecraft:glow_squid",
  "minecraft:witch",
  "minecraft:guardian",
  "minecraft:elder_guardian",
  "minecraft:endermite",
  "minecraft:magma_cube",
  "minecraft:strider",
  "minecraft:hoglin",
  "minecraft:zoglin",
  "minecraft:piglin",
  "minecraft:piglin_brute",
  "minecraft:goat",
  "minecraft:frog",
  "minecraft:trader_llama",
  "minecraft:camel",
  "minecraft:ghast",
  "minecraft:blaze",
  "minecraft:vindicator",
  "minecraft:evocation_illager",
  "minecraft:villager_v2",
  "minecraft:wandering_trader",
  "minecraft:zombie_villager_v2",
  "minecraft:phantom",
  "minecraft:pillager",
  "minecraft:ravager",
  "minecraft:iron_golem",
  "minecraft:sniffer",
  "minecraft:breeze",
  "minecraft:bogged",
];

system.runInterval(() => {
  // Get all crates in the world
  let crates = world
    .getDimension("overworld")
    .getEntities({ families: ["pb_plane_crate"] });
  crates = crates.concat(
    world.getDimension("nether").getEntities({ families: ["pb_plane_crate"] })
  );
  crates = crates.concat(
    world.getDimension("the_end").getEntities({ families: ["pb_plane_crate"] })
  );
  crates.forEach((crate) => {
    // Check if crate has a lead attached
    const attached = crate.getComponent("leashable").isLeashed;
    // Stop if no mob or lead attached
    if (attached) return;

    // If crate has a mob and is not attached - get all helicopters nearby
    if (!attached) {
      // Get the first rider (mob or entity inside the crate)
      const rider = crate.getComponent("rideable").getRiders()[0];
      try {
        if (mobAnimTypes.includes(rider.typeId)) {
          const riderTypeId = rider.typeId.replace("minecraft:", "");
          rider.playAnimation(`animation.pb_plane.${riderTypeId}.in_crate`, {
            blendOutTime: 0,
            stopExpression: "!query.is_riding",
          });
        }
      } catch (error) {}
      let helicopters = crate.dimension.getEntities({
        location: crate.location,
        maxDistance: 4,
        closest: 1,
        families: ["pb_plane_helicopter_cargo"],
      });
      // Check if the helicopter has cargo or a driver
      helicopters.forEach((helicopter) => {
        // Detect property to see if already has cargo
        const hasCargo = helicopter.getProperty("pb_plane:cargo_active");
        // CHeck if helicopter has driver
        const driver = helicopter.getComponent("rideable").getRiders().length;
        // Check if already has a crate
        const existingCrateId = helicopter.getDynamicProperty("crateId");
        // If the helicopter has cargo, or no driver, stop
        if (hasCargo == true || driver == 0 || existingCrateId != undefined)
          return;
        // if the helicopter has no cargo and has a driver, attach the crate to the helicopter with a lead
        if (hasCargo == false && driver > 0) {
          // Leash to helicopter
          crate.getComponent("leashable").leashTo(helicopter);
          // Set helicopter component to true (using event)
          helicopter.triggerEvent("pb_plane:cargo_active");
          // set property of crate to be that of the helicopter ID
          crate.setDynamicProperty("leash_holder", helicopter.id);
          helicopter.setDynamicProperty("crateId", crate.id);
        }
      });
    }
  });
}, 40);

//process script events
system.afterEvents.scriptEventReceive.subscribe((eventData) => {
  //id is for the id of the script command - sourceEntity is the entity that run the script command
  const { id, sourceEntity } = eventData;
  if (sourceEntity == null) return;
  // Lead check from crate a/c
  if (id == "pb_plane:leash_broken") {
    const leashHolderID = sourceEntity.getDynamicProperty("leash_holder");
    const leashHolder = getEntityByID(
      sourceEntity,
      "pb_plane:heli_cargo",
      leashHolderID
    );

    if (leashHolder == undefined) return;
    leashHolder.triggerEvent("pb_plane:cargo_inactive");
    leashHolder.addEffect("slowness", 1, {
      amplifier: 3,
      showParticles: false,
    });
    
    // Reset the heli's crateId property so it can pick up a new crate
    leashHolder.setDynamicProperty("crateId", undefined); // FIXED: This should be on leashHolder, not sourceEntity

    // Reset the heli's crateId property so it can pick up a new crate
    sourceEntity.setDynamicProperty("crateId", undefined);
    return;
  }
  // Drop Cargo run from helicopter a/c
  if (id == "pb_plane:drop_cargo") {
    const crateId = sourceEntity.getDynamicProperty("crateId");
    const crate = getEntityByID(sourceEntity, "pb_plane:cargo_crate", crateId);

    if (crateId == undefined) return;
    crate.getComponent("leashable").unleash();
    crate.triggerEvent("pb_plane:airdrop");
    crate.addEffect("slow_falling", 200, {
      amplifier: 0,
      showParticles: false,
    });
    // Reset the heli's crateId property so it can pick up a new crate
    sourceEntity.setDynamicProperty("crateId", undefined);
    return;
  }
});
function getEntityByID(sourceEntity, type, id) {
  const entities = sourceEntity.dimension.getEntities({ type: type });
  return entities.find((entity) => entity.id == id) || null;
}
