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


const particles = {
  "withercore:electric": "wc:electric_hit",
  "withercore:laser": "wc:laser_hit",
  "withercore:flame": "wc:flame_hit",
};

const itemsMainhandInfo = {
  "wc:grappling_hook": "Long press to use the §6Grappling Hook§r.",
  "wc:propeller_hat": "Wear the §cHat§r to use it.",
  "wc:jetpack": "Wear the §bJetpack§r to use it.",
  "wc:hand_driller": "Turn on §aON§r-",
  "wc:portal_generator": "Switch the §cGenerator§r + / Open the §cPortal§r ",
};
const itemsHeadInfo = {
  "wc:propeller_hat": " Toggle between the §cHat§r states.",
};

const itemsChestInfo = {
  "wc:jetpack": " Toggle between the §bJetpack§r states.",
};

const itemEventInfo = {
  "wc:propeller_hat": {
    property: "wc:is_using_propeller_hat",
    amp: 2,
    dp: "propeller_hat_id_on",
    offDp: "propeller_hat_id_off",
  },
  "wc:jetpack": {
    property: "wc:is_using_jetpack",
    amp: 3,
    dp: "jetpack_id_on",
    offDp: "jetpack_id_off",
  },
};

const faceToFunction = {
  Down: "below",
  North: "north",
  West: "west",
  South: "south",
  East: "east",
  Up: "above",
};
const notAllowedBlocks = [
  "minecraft:air",
  "minecraft:water",
  "minecraft:bedrock",
  "minecraft:flowing_water",
  "minecraft:flowing_lava",
  "minecraft:lava",
  "minecraft:portal",
  "minecraft:end_portal",
  "minecraft:end_portal_frame",
  "minecraft:fire",
  "minecraft:soul_fire",
  "minecraft:light_block",
  "minecraft:command_block",
  "minecraft:repeating_command_block",
  "minecraft:chain_command_block",
  "minecraft:barrier",
  "minecraft:structure_block",
  "minecraft:structure_void",
  "minecraft:border_block",
  "minecraft:reinforced_deepslate",
  "minecraft:frog_spawn",
  "minecraft:dragon_egg",
  "minecraft:barrel",
  "minecraft:heavy_core",
  "minecraft:trapped_chest",
  "minecraft:chest",
];

// Handle projectile hitting an entity
world.afterEvents.projectileHitEntity.subscribe(
  ({ projectile, location, dimension }) => {
    const id = projectile.typeId;
    if (particles[id]) {
      dimension.spawnParticle(particles[id], location);
    }
  }
);

// Handle projectile hitting a block
world.afterEvents.projectileHitBlock.subscribe(
  ({ projectile, location, dimension }) => {
    const id = projectile.typeId;

    if (id === "withercore:electric" || id === "withercore:laser") {
      dimension.spawnParticle("minecraft:camera_shoot_explosion", location);
    }

    if (id === "withercore:hook" && projectile.isValid()) {
      const leashedTo = projectile.getComponent("leashable")?.leashHolder;

      if (leashedTo) {
        system.runTimeout(() => {
          if (projectile.isValid()) {
            const headLocation = projectile.getHeadLocation();
            const pitch = Math.random() * 0.2 + 0.8;

            projectile.dimension.playSound("grappling_hook.hit", headLocation, {
              pitch,
            });
            leashedTo.playSound("grappling_hook.hit", { pitch });

            system.runTimeout(() => {
              leashedTo.addTag("no_fall_damage");
            }, 2);

            moveToDestination(leashedTo, projectile);
          }
        }, 10);
      }
    }
  }
);

// Register custom components
world.beforeEvents.worldInitialize.subscribe((event) => {
  // Grappling hook behavior
  event.itemComponentRegistry.registerCustomComponent("wc:grappling_hook", {
    onCompleteUse: ({ source }) => {
      const loc = source.getHeadLocation();
      const dir = source.getViewDirection();
      const pitch = Math.random() * 0.2 + 0.8;

      source.dimension.playSound("grappling_hook.fire", loc, {
        volume: 0.8,
        pitch,
      });

      const projectile = source.dimension.spawnEntity(
        "withercore:hook",
        vector3add(loc, dir)
      );
      projectile.getComponent("leashable").leashTo(source);
      projectile.getComponent("projectile").shoot(vector3multiply(dir, 4));

      source.setDynamicProperty("leashedEntityId", projectile.id);
      source.setProperty("wc:is_hooked", true);

      const intervalId = system.runInterval(() => {
        const isValid = projectile?.isValid();
        source.onScreenDisplay.setActionBar(
          "Press down §6'Shift'§r to retract the hook."
        );

        if (source.isSneaking || !isValid) {
          source.onScreenDisplay.setActionBar("");
          system.clearRun(intervalId);

          if (isValid) {
            system.runTimeout(() => projectile.remove());
          }

          source.setProperty("wc:is_hooked", false);
          source.setDynamicProperty("leashedEntityId", null);
        }
      });
    },
    onUse: ({ source }) => {
      const pitch = Math.random() * 0.2 + 0.8;
      source.dimension.playSound("grappling_hook.charge",source.getHeadLocation(),{ volume: 0.8, pitch });
      source.playAnimation("animation.player.grappling_hook.fire");
    },
  });

  // Jumping pad behavior
  event.blockComponentRegistry.registerCustomComponent("wc:jumping_pad", {
    onTick: ({ dimension, block }) => {
      const position = block.bottomCenter();
      dimension.spawnParticle("wc:jumping_pad", position);
      dimension.spawnParticle("wc:jumping_pad2", position);
    },
    onStepOn: ({ entity, block, dimension }) => {
      const position = block.center();
      dimension.spawnParticle("minecraft:camera_shoot_explosion", position);
      entity?.applyKnockback(0, 0, 0, 1.5);
      dimension.playSound("mob.breeze.jump", block.location);

      system.runTimeout(() => {
        entity.addTag("no_fall_damage");
      }, 2);
    },
  });

  // Drill behavior
  event.itemComponentRegistry.registerCustomComponent("wc:hand_driller", {
    onUseOn: (event) => {
      const { source } = event;
      const hdSwitch = source.getDynamicProperty("hand_driller_on");
  
      const stopDrilling = (source) => {
        const id = source.getDynamicProperty("hand_driller_on");
        try {system.clearRun(id)} catch (e){}
        source.setDynamicProperty("hand_driller_on", undefined);
        source.onScreenDisplay.setActionBar("Turn §aON§r-");
      };
  
      if (!hdSwitch) {  
        const processDrilling = () => {
          const blockInfo = source.getBlockFromViewDirection({ 
            maxDistance: 6, 
            includeLiquidBlocks: false, 
            excludeTypes: notAllowedBlocks 
          });
  
          const driller = source.getComponent("equippable")?.getEquipment("Mainhand");
  
          // Stop if no block is in range, sneaking, or wrong item type
          if (!blockInfo || source.isSneaking || driller.typeId !== "wc:hand_driller") {
            stopDrilling(source);
            return;
          }
          
          driller.getComponent("cooldown")?.startCooldown(source);
          source.onScreenDisplay.setActionBar("Turn §cOFF§r-");
          const { face: blockFace, block } = blockInfo;
          const actionFunction = faceToFunction[blockFace];
  
          // Get 3x3 blocks and apply drilling logic
          get3x3Blocks(block, blockFace).forEach((blc) => {
            const blockType = blc[actionFunction]?.();
  
            if (blockType?.typeId === "minecraft:air" && !notAllowedBlocks.includes(blc.typeId)) {
              blc.dimension.spawnParticle("wc:break", blc.center());
  
              const { x, y, z } = blc;
              system.runTimeout(() => {
                if (!source.getDynamicProperty("hand_driller_on")) return;
                blc.dimension.runCommand(`setblock ${x} ${y} ${z} air destroy`);
              }, 20);
            }
          });
        };
  
        // Execute once and set interval for continuous drilling
        processDrilling();
        const id = system.runInterval(() => {
          try {processDrilling()}
            catch (error) {system.clearRun(id);}
        }, 25);
        source.setDynamicProperty("hand_driller_on", id);
      } else {
        stopDrilling(source);
      }
    },
  });

  //Glove boxing behavior
  event.itemComponentRegistry.registerCustomComponent("wc:boxing_glove", {
    onUse: (event) => {
      const { source, itemStack} = event;
      const target = source.getEntitiesFromViewDirection({maxDistance:6})[0]?.entity
      const cooldown = itemStack.getComponent('cooldown')?.getCooldownTicksRemaining(source)
      if(cooldown < 19) return
      itemStack.getComponent('cooldown').startCooldown(source)
      if(!target) return
      const dir = source.getViewDirection();
      target.applyKnockback(dir.x,dir.z,2,0.25)
      target.applyDamage(2,{damagingEntity:source,cause:"entityAttack"})
      target.addEffect("nausea",80,{amplifier:2})
      
    }
  });

  //placeHelper portals spawning 
  event.itemComponentRegistry.registerCustomComponent("wc:portal_generator", {
    onUse: (event) => {
      const { source } = event;
      
      if(source.isSneaking){
        source.setProperty('wc:portal_type', source.getProperty('wc:portal_type') === 'blue' ? 'red' : 'blue');
        return
      }
      const useLoc = vector3add(source.getHeadLocation(), vector3multiply(source.getViewDirection(), 4));
      const loc = source.getBlockFromViewDirection({maxDistance: 8}) || source.dimension.getBlockFromRay(useLoc, { x: 0, y: -1, z: 0 });        
      if (!loc) return;
  
      const centerBlock = loc.block.above();
      const {x: cx, y: cy, z: cz} = centerBlock.location;
      const areaBlocks = [];
  
      // Gather blocks in a 3x3x3 area around the centerBlock
      for (let x = -1; x <= 1; x++) {
        for (let y = 0; y <= 2; y++) {
          for (let z = -1; z <= 1; z++) {
            const b = centerBlock.dimension.getBlock({x:x+cx, y:cy+y, z:cz+z});
            if(!b) continue;
            areaBlocks.push(b);
          }
        }
      }
  
      // Check if all blocks in the area are air        
      const isAir = !areaBlocks.every(b => b.typeId === "minecraft:air")
      if(isAir){
        for(const b of areaBlocks) if(b?.typeId !== "minecraft:air") b.dimension.spawnParticle("wc:exclamation", b.center());
        source.onScreenDisplay.setActionBar(" - You can't place a portal inside blocks!");
        source.dimension.playSound("break.suspicious_sand",centerBlock.center(),{pitch:0.6});
        return;
      } else {
        source.dimension.playSound("respawn_anchor.set_spawn",centerBlock.center())
        for(const b of areaBlocks) b.dimension.spawnParticle("minecraft:basic_flame_particle", b.center());
      }
  
      // Remove existing red portals
      const allPortals = dimensions.flatMap(dimension => dimension.getEntities({ type: "wc:portal" }));
      allPortals.filter(p => p.getProperty('wc:portal_type') === source.getProperty('wc:portal_type') && p.getDynamicProperty('wc:portal_id') === source.id)
                .forEach(redPortal => redPortal.remove());
  
      // Spawn a new portal
      const portal = source.dimension.spawnEntity("wc:portal", centerBlock.bottomCenter());
      portal.setDynamicProperty('wc:portal_id', source.id);
      portal.setProperty('wc:portal_type', source.getProperty('wc:portal_type'));
      portal.setRotation(source.getRotation());
    }
  });

});

// reset dynamic properties on player join
world.afterEvents.playerSpawn.subscribe((event) => {
  if(event.initialSpawn){
    event.player.setDynamicProperty("hand_driller_on", undefined);
    event.player.setDynamicProperty("propeller_hat_id_on", undefined);
    event.player.setDynamicProperty("propeller_hat_id_off", undefined);
    event.player.setDynamicProperty("jetpack_id_on", undefined);
    event.player.setDynamicProperty("jetpack_id_off", undefined);
  }
})

// Handle entity removal
world.beforeEvents.entityRemove.subscribe(({ removedEntity }) => {
  const player = removedEntity.getComponent("leashable")?.leashHolder;
  if (player) {
    player.setDynamicProperty("leashedEntityId", null);
    system.run(() => player.setProperty("wc:is_hooked", false));
  }
});

//handle /scriptevent
system.afterEvents.scriptEventReceive.subscribe((event) => {
  const player = event.sourceEntity;

    //driller_vehicle handler
    if (event.id === "wc:drill") {  
      const vehicle = event.sourceEntity;
      const isDrilling = vehicle.getProperty("wc:is_drilling");
      if (!isDrilling) {
        vehicle.setProperty("wc:is_drilling", true);
        const idDrill = system.runInterval(() => {
          const player = vehicle.getComponent("rideable")?.getRiders()[0];
          if (!player || !vehicle.getProperty("wc:is_drilling")) {
            vehicle.setProperty("wc:is_drilling", false);
            system.clearRun(idDrill);
            return;
          };
          player.onScreenDisplay.setActionBar("Turn §cOFF§r-");
          const blockHit = player.getBlockFromViewDirection({maxDistance:10})
          if (!blockHit){
            vehicle.runCommand("fill ~-1 ~2 ~-1 ~1 ~1 ~1 minecraft:air destroy");
            return
          }
          const {block , face} = blockHit;
          const actionFunction = faceToFunction[face];

          get3x3Blocks(block, face).forEach(blc => {
            const blockType = blc[actionFunction]?.();
  
            if (blockType?.typeId === "minecraft:air" && !notAllowedBlocks.includes(blc.typeId)) {
              blc.dimension.spawnParticle("wc:break", blc.center());
  
              const { x, y, z } = blc;
              system.runTimeout(() => {
                if (!vehicle.getProperty("wc:is_drilling")) return;
                blc.dimension.runCommand(`setblock ${x} ${y} ${z} air destroy`);
              }, 5);
            }
          })
        }, 10);
      } else {
        vehicle.setProperty("wc:is_drilling", false);
      }
    }

  //handle npc dialogue
  if(event.id === "wc:time_add") {
    let time = 0;
    const timeToAdd = Number(event.message)
    const id = system.runInterval(() => {        
      time += Math.abs(timeToAdd/60);
      if(time >= Math.abs(timeToAdd)) {
        system.clearRun(id);
        return;
      }
      event.sourceEntity.runCommandAsync('/time add ' +  timeToAdd/60)
    });
  }

  if (!event.id.includes("wc:") || event.message !== "mr_gadget_event") return;
  const handleItemEvent = (itemKey) => {
    const info = itemEventInfo[itemKey];
    if (!info) return;

    player.setProperty(info.property, true);
    const id = system.runInterval(() => {
      player.addEffect("levitation", 10, {
        showParticles: false,
        amplifier: info.amp,
      });
      player.onScreenDisplay.setActionBar(" §i'Sneak'§r to turn §cOFF§r.");
    });
    player.setDynamicProperty(info.dp, id); // Store interval ID
  };

  const clearItemEvent = (itemKey) => {
    const info = itemEventInfo[itemKey];
    if (!info) return;

    player.setProperty(info.property, false);

    const idOn = player.getDynamicProperty(info.dp);
    if (idOn) {
      system.clearRun(idOn);
      player.removeEffect("levitation");
      player.setDynamicProperty(info.dp, null);
    }

    const idOff = player.getDynamicProperty(info.offDp);
    if (idOff) {
      system.clearRun(idOff);
      player.removeEffect("slow_falling");
      player.setDynamicProperty(info.offDp, null);
    }
  };

  const handleItemOffEvent = (itemKey) => {
    const info = itemEventInfo[itemKey];
    if (!info) return;

    player.setProperty(info.property, true);
    const idOff = system.runInterval(() => {
      player.addEffect("slow_falling", 10, { showParticles: false });
      player.onScreenDisplay.setActionBar(" §i'Sneak'§r to turn §aON§r.");
    });
    player.setDynamicProperty(info.offDp, idOff);
  };

  // Handle specific events
  if (event.id === "wc:propeller_hat_on") {handleItemEvent("wc:propeller_hat");}
  if (["wc:propeller_hat_disabled", "wc:propeller_hat_off"].includes(event.id)) {clearItemEvent("wc:propeller_hat");}
  if (event.id === "wc:propeller_hat_off") {handleItemOffEvent("wc:propeller_hat");}
  if (event.id === "wc:jetpack_on") {handleItemEvent("wc:jetpack");}
  if (["wc:jetpack_disabled", "wc:jetpack_off"].includes(event.id)) {clearItemEvent("wc:jetpack");}
  if (event.id === "wc:jetpack_off") {handleItemOffEvent("wc:jetpack");}


  // Handle action bar info events
  if (event.id === "wc:action_bar_infos1") {
    const item = player.getComponent("equippable").getEquipment("Mainhand");
    if (!item) return;
    let info = itemsMainhandInfo[item.typeId];
    if (!info) return;
    if(player.getProperty("wc:portal_type") == "blue" && item.typeId == "wc:portal_generator") info = info.replace(/§c/g, "§3")
    
    player.onScreenDisplay.setActionBar(info);
  }

  if (event.id === "wc:action_bar_infos2") {
    const item = player.getComponent("equippable").getEquipment("Head");
    if (!item) return;
    const info = itemsHeadInfo[item.typeId];
    if (!info) return;
    player.onScreenDisplay.setActionBar(info);
  }

  if (event.id === "wc:action_bar_infos3") {
    const item = player.getComponent("equippable").getEquipment("Chest");
    if (!item) return;
    const info = itemsChestInfo[item.typeId];
    if (!info) return;
    player.onScreenDisplay.setActionBar(info);
  }
});

const popups = [
  {time:8, id:"wc:popup1"},
  {time:6, id:"wc:popup2"},
  {time:7, id:"wc:popup3"},
  {time:6, id:"wc:popup4"},
  {time:8, id:"wc:popup5"},
];
const lastSelected = new WeakMap();
const popupCooldown = new WeakMap();

const allDimensions = [ 'overworld', 'nether', 'the_end' ];
const dimensions = allDimensions.map(dimension => world.getDimension(dimension));

const portalCooldown = new WeakMap(); 
system.runInterval(() => {
  // Portals handler
  const allPortals = dimensions.flatMap(dimension => dimension.getEntities({type:"wc:portal"}));

  for(const portal of allPortals) {

      const id = portal.getDynamicProperty('wc:portal_id');
      if (!id) continue;
      const type = portal.getProperty('wc:portal_type')
      const linkedTo = allPortals.find(p => p.getDynamicProperty('wc:portal_id') === id && p.getProperty('wc:portal_type') !== type);
      if (!linkedTo) continue;

      const closeEntities = portal.dimension.getEntities({maxDistance: 0.5, location: portal.location,excludeTypes: ["wc:portal"]});
      for(const entity of closeEntities) {
        const cd = portalCooldown.get(entity)
        if(cd>Date.now()){
          portalCooldown.set(entity, Date.now() + 500);
          continue
        }
        if(entity.typeId == "minecraft:player"){
          entity.camera.fade({
            fadeColor:{
              red:type === 'red' ? 1 : 0,
              green:0,
              blue:type === 'red' ? 0 : 1
            },
            fadeTime:{
              fadeInTime:0.25,
              fadeOutTime:0.25,
              holdTime:0
            }
          }) 
        }
        portalCooldown.set(entity, Date.now() + 500);
        system.runTimeout(() => {
          system.runTimeout(() => {
            portal.dimension.playSound("mob.endermen.portal",portal.location,{pitch:0.5});
            linkedTo.dimension.playSound("mob.endermen.portal",linkedTo.location,{pitch:0.5})
          }, 2);
          entity.teleport(linkedTo.location,{dimension:linkedTo.dimension,rotation:linkedTo.getRotation()});
        }, entity.typeId == "minecraft:player" ? 5 : 0)
      }
  }

  const mr_gadget = dimensions.flatMap(dimension => dimension.getEntities({type:"wc:mr_gadget"}));

  for(const gadget of mr_gadget) {
    let mr_gadget_cooldown = popupCooldown.get(gadget);
    if(!mr_gadget_cooldown) mr_gadget_cooldown = 0;
    const player = gadget.dimension.getEntities({type:"minecraft:player", maxDistance: 8, location: gadget.location})[0];
    if(mr_gadget_cooldown <= 0 && player) {
      let popup = popups[Math.floor(Math.random() * popups.length)];
      const last = lastSelected.get(gadget);
      while (popup.id == last) popup = popups[Math.floor(Math.random() * popups.length)];
      lastSelected.set(gadget, popup.id);

      const loc = {x:gadget.location.x,y:gadget.location.y + 3,z:gadget.location.z};
      gadget.dimension.spawnParticle(popup.id,loc);
      popupCooldown.set(gadget, 600);
      continue;
    }

    mr_gadget_cooldown-=5;
    popupCooldown.set(gadget, mr_gadget_cooldown);
  }

},5)


// Helper functions
function moveToDestination(player,projectile,horizontalStrength = 0.75,verticalStrength = 0.75) {
  const intervalId = system.runInterval(() => {
    if (!projectile?.isValid()) {system.clearRun(intervalId);return;}
    const { x: px, y: py, z: pz } = player.location;
    const { x: dx, y: dy, z: dz } = projectile.location;
    let directionX = dx - px;
    let directionY = dy - py;
    let directionZ = dz - pz;
    const magnitude = Math.sqrt(directionX ** 2 + directionY ** 2 + directionZ ** 2);
    if (magnitude > 0) {directionX /= magnitude;directionY /= magnitude;directionZ /= magnitude;}
    player.applyKnockback(directionX,directionZ,horizontalStrength,directionY * verticalStrength);
  });
}

function vector3multiply(vec, multiplier) {
  return {x: vec.x * multiplier,y: vec.y * multiplier,z: vec.z * multiplier};
}

function vector3add(vec1, vec2) {
  return {x: vec1.x + vec2.x,y: vec1.y + vec2.y,z: vec1.z + vec2.z};
}

function get3x3Blocks(hitBlock, blockFace) {
  const dimension = hitBlock.dimension;
  const { x: baseX, y: baseY, z: baseZ } = hitBlock.location;

  const faceOffsets = {
    Up: {x: [1, 1, 1, 0, 0, 0, -1, -1, -1],y: 0,z: [1, 0, -1, 1, 0, -1, 1, 0, -1],},
    Down: {x: [1, 1, 1, 0, 0, 0, -1, -1, -1],y: 0,z: [1, 0, -1, 1, 0, -1, 1, 0, -1],},
    North: {x: [1, 0, -1, 1, 0, -1, 1, 0, -1],y: [1, 1, 1, 0, 0, 0, -1, -1, -1],z: 0,},
    South: {x: [1, 0, -1, 1, 0, -1, 1, 0, -1],y: [1, 1, 1, 0, 0, 0, -1, -1, -1],z: 0,},
    West: {x: 0,y: [1, 1, 1, 0, 0, 0, -1, -1, -1],z: [1, 0, -1, 1, 0, -1, 1, 0, -1],},
    East: {x: 0,y: [1, 1, 1, 0, 0, 0, -1, -1, -1],z: [1, 0, -1, 1, 0, -1, 1, 0, -1],},
  };

  const offsets = faceOffsets[blockFace];

  const blocks = [];
  for (let i = 0; i < 9; i++) {
    const x = baseX + (Array.isArray(offsets.x) ? offsets.x[i] : offsets.x);
    const y = baseY + (Array.isArray(offsets.y) ? offsets.y[i] : offsets.y);
    const z = baseZ + (Array.isArray(offsets.z) ? offsets.z[i] : offsets.z);

    blocks.push(dimension.getBlock({ x, y, z }));
  }
  return blocks;
}

// Display entities handler
const displayedEntityItem = [
  {item:"wc:driller_vehicle_spawn_egg", info:"§aDriller.\nAllow you to dig 3x3 area\nand move around the world."},
  {item:"wc:computer_spawn_egg", info:"§aComputer.\nAllows to perform various\ntasks in the Map."},
  {item:"wc:drone_spawn_egg", info:"§3Drone.\nAttacks mobs that are\nhostile towards its owner.\n§i-----info-----\n§iUse  on the drone\n§ito turn it ON."},
  {item:"withercore:electric_turret_spawn_egg", info:"§aElectric Turret.\nShoots electric bolts to\nattack nearby Hostile mobs."},
  {item:"withercore:flame_turret_spawn_egg", info:"§pFlame Turret.\nShoots fire balls to\nattack nearby Hostile mobs."},
  {item:"withercore:laser_turret_spawn_egg", info:"§cLaser Turret.\nShoots laser beams to\nattack nearby Hostile mobs."},
  {item:"wc:mecha_spawn_egg", info:"§eMecha.\nPlayer can mount\nand control it."}, 
  {item:"wc:gadget_cart_spawn_egg", info:"§4Gadget Cart.\nAllows you to move\naround the world."}, 
  {item:"wc:mr_gadget_spawn_egg", info:"Test"},
  {item:"wc:portal_spawn_egg", info:"Test"},
  {item:"wc:boxing_glove", info:"§3Boxing Glove.\nAllow you to attack mobs.\nCauses small damage\nand nausea effect."},
  {item:"wc:propeller_hat", info:"§cPropeller Hat.\nAllows you to fly.\n§i-----How to use-----\n§i To toggle Fly or Land."},
  {item:"wc:grappling_hook", info:"§eGrappling Hook.\nAllow the player to\nswing and move around.\n§i-----How to use-----\n§i To shoot the hook.\n§i To release the hook."},
  {item:"wc:jetpack", info:"§bJetpack.\nAllows you to fly.\n§i-----How to use-----\n§i To toggle Fly or Land."},
  {item:"wc:hand_driller", info:"§3Hand Driller.\nBreaks a 3x3 block area\n§i-----How to use-----\n§i to turn on ON or OFF"},
  {item:"wc:portal_generator", info:"§3Portal §cGenerator.\nAllows you to open portals\nthat you can teleport between\n§i-----How to use-----\n§iSwitch the Generator +\n§iOpen the Portal ."},
  {item:"wc:jumping_pad", info:"§bJumping Pad.\nLaunches any player who\nsteps on it upwards."},
]

const skipTypes = [8,9]; //skipping mr_gadget and portal (used them for testing)

world.beforeEvents.playerInteractWithEntity.subscribe((event) => {
  const { target, player } = event;
  if (target.typeId !== "wc:display_entities") return;
  
  const type = target.getProperty("wc:entity_type");
  const gameMode = player.getGameMode();
  
  system.run(() => {
    if (gameMode === "creative") {
      target.dimension.playSound("random.click", target.location);
      
      const dir = player.getViewDirection();
      const loc = player.getHeadLocation();
      const particleLoc = { x: loc.x + dir.x, y: loc.y + dir.y, z: loc.z + dir.z };
      
      let nextType;
      
      if (player.isSneaking) {
        nextType = type === 0 ? 16 : type - 1;
        while (skipTypes.includes(nextType)) nextType -= 1;
        target.dimension.spawnParticle("wc:minus", particleLoc);
      } else {
        nextType = type === 16 ? 0 : type + 1;
        while (skipTypes.includes(nextType)) nextType += 1;
        target.dimension.spawnParticle("wc:plus", particleLoc);
      }
      
      target.setProperty("wc:entity_type", nextType);      
      target.nameTag = displayedEntityItem[nextType].info + "\n§i-------------\n To obtain the item.\n ";
    } else {
      const container = player.getComponent("inventory").container;
      const item = new ItemStack(displayedEntityItem[type].item);
      const isFull = container.addItem(item);
      
      if (isFull) {
        player.dimension.spawnItem(isFull, player.location);
        player.playSound("random.pop2");
      } else {
        player.playSound("random.pop");
      }
    }
  });
});

world.afterEvents.entitySpawn.subscribe((event) => {
  const { entity } = event;
  if (entity.typeId !== "wc:display_entities") return;
  entity.nameTag = displayedEntityItem[0].info + "\n§i-------------\n To obtain the item.\n ";
});

const removeOnHit = [
  "wc:mr_gadget",
  "wc:portal",
  "wc:display_entities"
]
world.afterEvents.entityHitEntity.subscribe((event) => {
  const {hitEntity, damagingEntity} = event;
  if(damagingEntity.typeId !== "minecraft:player") return;
  if(damagingEntity.getGameMode() !== "creative") return;
  if(!removeOnHit.includes(hitEntity.typeId)) return;
  hitEntity.remove();
});