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

// Configuration for each custom moss block.
const mossConfigs = {
  "hb_hr:black_moss": {
    // An array of block types that can be replaced by this moss.
    spreadTargets: ["minecraft:stone"],
    // List of vegetation that can be placed above the moss (e.g. carpet, grass, etc.).
    vegetation: ["hb_hr:black_moss_carpet", "hb_hr:black_grass"],
    // Chance to place vegetation on top.
    vegetationChance: 0.4,
    // Radius (in blocks) for the spreading effect.
    spreadRadius: 3,
    // Chance mapping based on Chebyshev “ring” distance.
    ringChances: { 1: 0.7, 2: 0.6, 3: 0.5 },
  },
};

export function mossBehavior() {
  world.beforeEvents.worldInitialize.subscribe((event) => {
    event.blockComponentRegistry.registerCustomComponent("hb_hr:moss", {
      onPlayerInteract(data) {
        const { player, block } = data;
        if (!player || !block) return;

        // Retrieve the configuration for this moss block based on its typeId.
        const config = mossConfigs[block.typeId];
        if (!config) return; // No config? Exit early.

        // Check if the player is holding bonemeal in their main hand.
        const equipment = player.getComponent("equippable");
        const mainhand = equipment?.getEquipment("Mainhand");
        if (!mainhand || mainhand.typeId !== "minecraft:bone_meal") return;

        // Play bonemeal effects.
        const center = block.center();
        block.dimension.playSound("item.bone_meal.use", center);
        block.dimension.spawnParticle("minecraft:crop_growth_emitter", center);

        // Consume one bonemeal if the player is not in creative mode.
        if (player.getGameMode() !== GameMode.creative) {
          equipment?.setEquipment("Mainhand", decreaseStack(mainhand));
        }

        // Read parameters from the config.
        const radius = config.spreadRadius;
        const targetTypes = config.spreadTargets; // Now an array of valid targets.
        const ringChances = config.ringChances;
        const vegetationChance = config.vegetationChance;
        const vegetationArray = config.vegetation;

        // Iterate in a 3D sphere (cube checked with a Euclidean distance test).
        for (let dx = -radius; dx <= radius; dx++) {
          for (let dy = -radius; dy <= radius; dy++) {
            for (let dz = -radius; dz <= radius; dz++) {
              // Skip the original block.
              if (dx === 0 && dy === 0 && dz === 0) continue;

              // Only process positions within the sphere.
              const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
              if (distance > radius) continue;

              // Determine the “ring” using Chebyshev distance.
              const ring = Math.max(Math.abs(dx), Math.abs(dy), Math.abs(dz));
              // Get the chance from the config; if not defined, use the minimum chance.
              let chance = ringChances[ring] ?? Math.min(...Object.values(ringChances));

              // If our random roll passes...
              if (Math.random() < chance) {
                const pos = {
                  x: block.location.x + dx,
                  y: block.location.y + dy,
                  z: block.location.z + dz,
                };
                const targetBlock = block.dimension.getBlock(pos);
                // Check if this block is one of the valid targets.
                if (targetBlock && targetTypes.includes(targetBlock.typeId)) {
                  // Replace the target block with our custom moss block.
                  block.dimension.setBlockType(pos, block.typeId);

                  // With a vegetation chance, try to place vegetation on top.
                  if (Math.random() < vegetationChance) {
                    const abovePos = { x: pos.x, y: pos.y + 1, z: pos.z };
                    const aboveBlock = block.dimension.getBlock(abovePos);
                    if (aboveBlock && aboveBlock.typeId === "minecraft:air") {
                      // Randomly pick one vegetation block from the array.
                      const vegetationBlock = vegetationArray[Math.floor(Math.random() * vegetationArray.length)];
                      block.dimension.setBlockType(abovePos, vegetationBlock);
                    }
                  }
                }
              }
            }
          }
        }
      },
    });
  });
}

// Helper: decrease bonemeal stack by one.
function decreaseStack(item) {
  if (item.amount > 1) {
    item.amount = item.amount - 1;
    return item;
  } else {
    return undefined;
  }
}
