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

// Map between a regular grass block and its tall (double) grass counterpart.
const GRASS_MAP = {
  "hb_hr:cursed_grass": "hb_hr:cursed_tall_grass",
  "hb_hr:black_grass": "hb_hr:black_tall_grass",
};

// Map for the drop item corresponding to the grass plant type.
// Both the original and the tall variant keys map to the desired drop.
const GRASS_DROP_MAP = {
  "hb_hr:cursed_grass": "hb_hr:cursed_grass",
  "hb_hr:black_grass": "hb_hr:black_grass",
};

export function grassPlant() {
  // Register the custom block component for the grass plant.
  // This allows the block to react to bonemeal usage.
  world.beforeEvents.worldInitialize.subscribe((event) => {
    event.blockComponentRegistry.registerCustomComponent("hb_hr:grass_plant", {
      // Optionally, handle natural growth in onRandomTick.

      // When a player interacts with the block.
      onPlayerInteract(data) {
        const { player, block } = data;
        if (!player || !block) return;

        const equippable = player.getComponent("equippable");
        const mainhandItem = equippable?.getEquipment(EquipmentSlot.Mainhand);
        if (!mainhandItem) return;

        // Handle bonemeal interaction.
        if (mainhandItem.typeId === "minecraft:bone_meal") {
          // Verify there is space above (not at top of world and block above is air).
          if (block.location.y + 1 >= block.dimension.heightRange.max) return;
          const blockAbove = block.above();
          if (!blockAbove || !blockAbove.isAir) return;

          const center = block.center();
          block.dimension.playSound("item.bone_meal.use", center);
          block.dimension.spawnParticle("minecraft:crop_growth_emitter", center);
          if (player.getGameMode() !== GameMode.creative) {
            equippable.setEquipment(EquipmentSlot.Mainhand, decreaseStack(mainhandItem));
          }

          // Look up the new type from GRASS_MAP.
          const newType = GRASS_MAP[block.typeId] || "minecraft:tall_grass";

          // Convert the block into a double tall grass.
          // Lower half: set the block type, add the custom tag, and set the "upper_block_bit" to false.
          block.setType(newType);
          block.setPermutation(block.permutation.withState("hb_hr:upper_block_bit", false));

          // Schedule placement of the upper half (after 1 tick).
          system.runTimeout(() => {
            // Double-check that the block above is still air.
            if (!blockAbove.isAir) return;
            blockAbove.setType(newType);
            // Initialize the upper half permutation from the lower block type.
            blockAbove.setPermutation(BlockPermutation.resolve(newType));
            // Set the state flag so that it marks the upper half.
            blockAbove.setPermutation(blockAbove.permutation.withState("hb_hr:upper_block_bit", true));
            // Optionally, you can add the tag if needed:
            // blockAbove.addTag("hb_hr:grass_plant");
          }, 1);
        }
      },
    });
  });

  // Handle block breaking for double tall grass (both halves).
  // When broken with scissors, the block will drop its mapped item; otherwise, it drops nothing.
  world.beforeEvents.playerBreakBlock.subscribe((data) => {
    const block = data.block;
    // Only process blocks that have our custom grass plant tag.
    if (!block.hasTag("hb_hr:grass_plant")) return;

    // Cancel the default break so that no drops occur automatically.
    data.cancel = false;
    const player = data.player;
    const equippable = player.getComponent("equippable");
    const mainhandItem = equippable?.getEquipment(EquipmentSlot.Mainhand);
    const usingScissors = mainhandItem && mainhandItem.typeId === "minecraft:shears";

    if (usingScissors) {
      // Look up the drop item from GRASS_DROP_MAP based on the block's type.
      const dropType = GRASS_DROP_MAP[block.typeId] || null;
      // Create and spawn the drop.
      if (!dropType) return;
      const drop = new ItemStack(dropType, 1);
      system.run(() => {
        block.dimension.spawnItem(drop, block.location);
      });
    }

    /* // Remove both halves of the double tall grass.
    system.run(() => {
      breakDoubleGrassPlant(block);
    });*/
  });

  // (Optional) Handle explosions by removing any impacted grass plant blocks.
  world.beforeEvents.explosion.subscribe((event) => {
    const grassBlocks = event.getImpactedBlocks().filter((blk) => blk.hasTag("hb_hr:grass_plant"));
    for (const blk of grassBlocks) {
      system.runTimeout(() => {
        blk.setType("minecraft:air");
      }, 1);
    }
  });

  // Utility function that decreases an item stack (similar to the sapling logic).
  function decreaseStack(item) {
    if (item.amount > 1) {
      item.amount -= 1;
      return item;
    } else {
      return undefined;
    }
  }

  // Function to break a double tall grass plant.
  // It determines the corresponding half (lower or upper) and removes both.
  function breakDoubleGrassPlant(brokenBlock) {
    let otherBlock;
    const isUpper = brokenBlock.permutation.getState("hb_hr:upper_block_bit");
    if (isUpper) {
      try {
        otherBlock = brokenBlock.below();
      } catch (e) {}
    } else {
      try {
        otherBlock = brokenBlock.above();
      } catch (e) {}
    }
    if (otherBlock && otherBlock.hasTag("hb_hr:grass_plant")) {
      otherBlock.setType("minecraft:air");
    }
    brokenBlock.setType("minecraft:air");
  }
}
