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

const cursedLichenComponent = {
  onTick({ block }) {
    // Get the center and origin of the block
    switch (block.typeId) {
      case "hb_hr:cursed_vine_new":
        if (system.currentTick % 20 == 0) {
        }
    }
  },
};

const customComponents = {
  "hb_hr:cursed_vine_new": cursedLichenComponent,
};

export class lichenHandler {
  static initialized = false;
  static playerBiomeMap = new Map(); // Speichert zuletzt erkannte Biome für jeden Spieler

  constructor() {
    this.initialize();
  }

  initialize() {
    if (!lichenHandler.initialized) {
      lichenHandler.initialized = true;
      this.processSubscriptions();
    }
  }

  processSubscriptions() {
    // Use this world initialization event to register all custom components
    world.beforeEvents.worldInitialize.subscribe(({ blockComponentRegistry }) => {
      for (const [componentName, componentImplementation] of Object.entries(customComponents)) {
        blockComponentRegistry.registerCustomComponent(componentName, componentImplementation);
      }
    });
    world.beforeEvents.playerInteractWithBlock.subscribe((event) => {
      if (!event.itemStack) return;
      if (event.itemStack.typeId !== "hb_hr:cursed_vine_new") return;
      if (event.block.typeId !== "hb_hr:cursed_vine_new") return;

      // Defer the actual permutation change until after the interaction
      system.run(() => {
        let face = getFaceFromBlocks(event.block, event.player.getBlockFromViewDirection({ excludeTypes: ["hb_hr:cursed_vine_new"] }).block);

        // 4. Map that face to your vine‐state key
        const faceToStateProp = {
          down: "hb_hr:floor_vine",
          north: "hb_hr:north_vine",
          east: "hb_hr:east_vine",
          south: "hb_hr:south_vine",
          west: "hb_hr:west_vine",
          // we ignore "down" here, or you could map it if desired
        };

        const stateKey = faceToStateProp[face];
        if (!stateKey) {
          // clicked the bottom face, or something unmapped
          return;
        }

        // 5. Pull current permutation, flip only that face’s state to true
        const perm = event.block.permutation;
        const newStates = {
          "hb_hr:floor_vine": perm.getState("hb_hr:floor_vine"),
          "hb_hr:north_vine": perm.getState("hb_hr:north_vine"),
          "hb_hr:east_vine": perm.getState("hb_hr:east_vine"),
          "hb_hr:south_vine": perm.getState("hb_hr:south_vine"),
          "hb_hr:west_vine": perm.getState("hb_hr:west_vine"),
        };
        const oldState = perm.getState(stateKey);
        newStates[stateKey] = true;

        // Wenn es vorher false war, also wirklich neu gesetzt wird:
        if (!oldState) {
          // Inventory-Component holen
          const invComp = event.player.getComponent("minecraft:inventory");
          const container = invComp.container;

          // Slotweise durchsuchen, first match
          for (let slot = 0; slot < container.size; slot++) {
            const stack = container.getItem(slot);
            if (stack && stack.typeId === "hb_hr:cursed_vine_new") {
              // nur dekrementieren, wenn tatsächlich noch mindestens 1 im Stack ist
              if (stack.amount > 1) {
                stack.amount--;
                container.setItem(slot, stack);
              } else {
                // Stack ist 0 → Slot leeren
                container.setItem(slot, undefined);
              }

              break;
            }
          }
        }

        // 6. Apply the updated permutation
        const newPerm = BlockPermutation.resolve(event.block.typeId, newStates);
        event.block.setPermutation(newPerm);

        // (optional) debug print
        //world.sendMessage(`Set ${stateKey} via face “${face}”`);
      });

      // Prevent the normal interact/placement behavior
      event.cancel = true;
    });
    world.beforeEvents.itemUseOn.subscribe((event) => {
      const { block, source: player, itemStack, blockFace } = event;
      if (!itemStack || !itemStack.typeId.includes("hb_hr:") || !itemStack.typeId.includes("cursed_vine")) return;

      system.run(() => {
        // //world.sendMessage("####init blockface: " + blockFace);
        // //world.sendMessage("####block: " + block.typeId);
        // //world.sendMessage("####blockabove: " + block.above().typeId);
        // 1. Take the face string and lowercase its first letter
        //    e.g. "West" → "west"
        let face = blockFace.charAt(0).toLowerCase() + blockFace.slice(1);
        // //world.sendMessage("first face:+++" + face);
        if (face === "down") {
          player.dimension.runCommand("/fill " + block.below().location.x + " " + block.below().location.y + " " + block.below().location.z + " " + block.below().location.x + " " + block.below().location.y + " " + block.below().location.z + " air destroy");
          // //world.sendMessage("Clicked bottom face – nothing to do.");
          return;
        }
        // 2. Reverse it to the opposite side
        const opposite = {
          north: "south",
          south: "north",
          east: "west",
          west: "east",
          up: "down",
        };
        face = opposite[face] || face; // fallback in case it's something weird

        // //world.sendMessage("#########face: " + face.toString());

        // 3. Map to your vine-state key
        const faceToStateProp = {
          down: "hb_hr:floor_vine", // if you actually want floor-vine on down
          north: "hb_hr:north_vine",
          east: "hb_hr:east_vine",
          south: "hb_hr:south_vine",
          west: "hb_hr:west_vine",
        };
        const stateKey = faceToStateProp[face];

        for (const [key, value] of Object.entries(stateKey)) {
          // //world.sendMessage("faces: " + key + "=" + value);
        }
        // //world.sendMessage(stateKey + "sddddddddddddddd");

        if (!stateKey) {
          // //world.sendMessage("no face detected######");
          return;
        } // nothing to do if it's an unmapped face

        // 4. Fetch the vine block and flip that face on
        const vineBlock = getAdjacentBlock(block, blockFace);
        // //world.sendMessage("ä###########" + vineBlock.typeId);
        if (vineBlock.typeId != "hb_hr:cursed_vine_new") {
          player.dimension.runCommand("/fill " + block.below().location.x + " " + block.below().location.y + " " + block.below().location.z + " " + block.below().location.x + " " + block.below().location.y + " " + block.below().location.z + " air destroy");
          // //world.sendMessage("WREONG BLOCK.");
          return;
        }
        // const vineBlock = block.above();
        const perm = vineBlock.permutation;
        const newStates = {
          "hb_hr:floor_vine": false,
          "hb_hr:north_vine": false,
          "hb_hr:east_vine": false,
          "hb_hr:south_vine": false,
          "hb_hr:west_vine": false,
        };
        newStates[stateKey] = true;

        for (const [key, value] of Object.entries(newStates)) {
          // //world.sendMessage(key + "=" + value);
        }

        const newPerm = BlockPermutation.resolve(vineBlock.typeId, newStates);
        vineBlock.setPermutation(newPerm);

        // //world.sendMessage(`Set ${stateKey} via face “${face}”`);
      });
    });

    world.beforeEvents.itemUse.subscribe((event) => {
      const player = event.source;
      const item = event.itemStack;

      if (item.typeId != "hb_hr:cursed_vine_new") return;
    });
    world.afterEvents.playerPlaceBlock.subscribe((event) => {
      const block = event.block;
      const player = event.player;

      breakVines(event.block);

      // //world.sendMessage(block.above().typeId);

      // switch (block.typeId) {
      //   case "hb_hr:cursed_vine_new":
      //     break;
      //   case "hb_hr:gravestone":
      //     //world.sendMessage("greavestone");
      //     const randomTexture = Math.floor(Math.random() * 3);
      //     const baseStates = {
      //       "hb_hr:random_texture": randomTexture,
      //       "hb_hr:open": block.permutation.getState("hb_hr:open"),
      //       "hb_hr:waterlogged": block.permutation.getState("hb_hr:waterlogged"),
      //       "hb_hr:powered": block.permutation.getState("hb_hr:powered"),
      //       "minecraft:cardinal_direction": block.permutation.getState("minecraft:cardinal_direction"),
      //       "minecraft:vertical_half": block.permutation.getState("minecraft:vertical_half"),
      //     };
      //     const newPerm = BlockPermutation.resolve(block.typeId, baseStates);
      //     block.setPermutation(newPerm);
      //     break;
      // }
    });
    world.beforeEvents.playerBreakBlock.subscribe((event) => {
      let breakFlag = false;
    });
    world.afterEvents.playerBreakBlock.subscribe((event) => {
      const block = event.brokenBlockPermutation;
      const usedItem = event.itemStackAfterBreak;
      const player = event.player;
      let blockItem = "empty";
      const seedDropChance = 0.875;

      if (block.type.id != "hb_hr:cursed_vine_new") {
        const aboveBlock = event.block.above();
        const northBlock = event.block.north();
        const eastBlock = event.block.east();
        const southBlock = event.block.south();
        const westBlock = event.block.west();
        // //world.sendMessage(northBlock.typeId);
        // //world.sendMessage(eastBlock.typeId);
        // //world.sendMessage(southBlock.typeId);
        // //world.sendMessage(westBlock.typeId);

        if (aboveBlock && aboveBlock.typeId == "hb_hr:cursed_vine_new") checkIfTopVineNeedsToBreak(aboveBlock, event.block);
        if (northBlock && northBlock.typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreak(northBlock, event.block);
        if (eastBlock && eastBlock.typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreak(eastBlock, event.block);
        if (southBlock && southBlock.typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreak(southBlock, event.block);
        if (westBlock && westBlock.typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreak(westBlock, event.block);
      }

      // player breaks cursed vine
      if (event.brokenBlockPermutation.type.id == "hb_hr:cursed_vine_new") {
        const perm = event.brokenBlockPermutation;
        const allStates = perm.getAllStates();
        //world.sendMessage(allStates.toString());
        let counter = 0;
        let directionArray = [];
        for (const [key, value] of Object.entries(allStates)) {
          //world.sendMessage(key + "=" + value);
          if (key.includes("_vine") && value == true) {
            directionArray.push(key);
            counter++;
          }
        }
        //world.sendMessage(counter.toString());
        // only one vine is inside the block active so detroy the block
        if (counter == 1) {
          //world.sendMessage(directionArray[0].toString());
          //world.sendMessage("break full block");
          if (!directionArray[0].includes("floor")) {
            if (event.block.below().typeId == "hb_hr:cursed_vine_new") {
              //world.sendMessage("remove here###########");
              player.dimension.runCommand("/fill " + event.block.location.x + " " + event.block.location.y + " " + event.block.location.z + " " + event.block.location.x + " " + event.block.location.y + " " + event.block.location.z + " air destroy");
              // checkIfVineNeedsToBreak(event.block, event.block);
              // system.runTimeout(() => {
              //   destroySingleSideVines(player, event.block, directionArray[0]);
              // }, 20);
            }
          }
          // else destroyAllSideVines(player, event.block);
        } else {
          //world.sendMessage("EVNT BLOCK" + event.block.typeId);

          if (event.player.getBlockFromViewDirection()) {
            // 1. Grab the two block positions
            const basePos = event.player.getBlockFromViewDirection().block.location;
            // const basePos = event.block.location;
            const hitBlock = event.block;
            const hitPos = hitBlock.location;
            // 2. Compute delta
            const dx = hitPos.x - basePos.x;
            const dy = hitPos.y - basePos.y;
            const dz = hitPos.z - basePos.z;
            // 3. Determine which face that corresponds to
            let face;
            if (dx === 1 && dy === 0 && dz === 0) face = "east";
            else if (dx === -1 && dy === 0 && dz === 0) face = "west";
            else if (dy === 1 && dx === 0 && dz === 0) face = "up";
            else if (dy === -1 && dx === 0 && dz === 0) face = "down";
            else if (dz === 1 && dx === 0 && dy === 0) face = "south";
            else if (dz === -1 && dx === 0 && dy === 0) face = "north";
            else {
              // Unexpected; not adjacent?
              //world.sendMessage(`Unknown face delta: (${dx},${dy},${dz})`);
              return;
            } //   //world.sendMessage(event.player.getBlockFromViewDirection().block.typeId);
            //   //world.sendMessage(event.block.typeId);
            //   // let face = getFaceFromBlocks(brokenBlock, vineBlock);
            //   let face = getFaceFromBlocks(event.block, event.player.getBlockFromViewDirection().block);
            // 4. Map that face to your vine‐state key
            const faceToStateProp = {
              up: "hb_hr:floor_vine",
              south: "hb_hr:north_vine",
              west: "hb_hr:east_vine",
              north: "hb_hr:south_vine",
              east: "hb_hr:west_vine",
              // we ignore "down" here, or you could map it if desired
            };
            const stateKey = faceToStateProp[face];
            if (!stateKey) {
              //world.sendMessage("return statekey err");
              // clicked the bottom face, or something unmapped
              return;
            }
            event.block.setType("hb_hr:cursed_vine_new");
            const newVine = event.block;
            //world.sendMessage("newvbine: " + newVine.typeId);
            // 5. Pull current permutation, flip only that face’s state to true
            const perm = newVine.permutation;
            const newStates = {
              "hb_hr:floor_vine": event.brokenBlockPermutation.getState("hb_hr:floor_vine"),
              "hb_hr:north_vine": event.brokenBlockPermutation.getState("hb_hr:north_vine"),
              "hb_hr:east_vine": event.brokenBlockPermutation.getState("hb_hr:east_vine"),
              "hb_hr:south_vine": event.brokenBlockPermutation.getState("hb_hr:south_vine"),
              "hb_hr:west_vine": event.brokenBlockPermutation.getState("hb_hr:west_vine"),
            };
            newStates[stateKey] = false;
            // 6. Apply the updated permutation
            const newPerm = BlockPermutation.resolve(event.block.typeId, newStates);
            newVine.setPermutation(newPerm);
            checkIfVineNeedsToBreak(event.player.getBlockFromViewDirection().block.below(), event.block.below());
          } else {
            //world.sendMessage("err2");

            const blockPos = event.block.location;

            // 1. Hol die Blickrichtung (unit Vector3)
            const viewDir = player.getViewDirection(); // { x, y, z } normalisiert

            // 2. Invertiere, damit es "hinter" dem Spieler zeigt
            const backX = viewDir.x;
            const backZ = viewDir.z;

            // 3. Auf die stärkste Komponente runden für eine der vier Richtungen
            let offX = 0,
              offZ = 0;
            if (Math.abs(backX) > Math.abs(backZ)) {
              // stärker in X-Richtung → Ost/West
              offX = Math.sign(backX); // +1 = West, -1 = Ost
            } else {
              // stärker in Z-Richtung → Süd/Nord
              offZ = Math.sign(backZ); // +1 = Süd,  -1 = Nord
            }

            // 4. Bestimme Ziel-Position genau einen Block dahinter
            const behindPos = {
              x: blockPos.x + offX,
              y: blockPos.y,
              z: blockPos.z + offZ,
            };

            // 5. Setze dort einen Goldblock
            const dim = player.dimension;
            const behindBlock = dim.getBlock(behindPos);

            // 1. Grab the two block positions
            const basePos = behindPos;
            // const basePos = event.block.location;
            const hitBlock = event.block;
            const hitPos = hitBlock.location;
            // 2. Compute delta
            const dx = hitPos.x - basePos.x;
            const dy = hitPos.y - basePos.y;
            const dz = hitPos.z - basePos.z;
            // 3. Determine which face that corresponds to
            let face;
            if (dx === 1 && dy === 0 && dz === 0) face = "east";
            else if (dx === -1 && dy === 0 && dz === 0) face = "west";
            else if (dy === 1 && dx === 0 && dz === 0) face = "up";
            else if (dy === -1 && dx === 0 && dz === 0) face = "down";
            else if (dz === 1 && dx === 0 && dy === 0) face = "south";
            else if (dz === -1 && dx === 0 && dy === 0) face = "north";
            else {
              // Unexpected; not adjacent?
              //world.sendMessage(`Unknown face delta: (${dx},${dy},${dz})`);
              return;
            } //   //world.sendMessage(event.player.getBlockFromViewDirection().block.typeId);
            //   //world.sendMessage(event.block.typeId);
            //   // let face = getFaceFromBlocks(brokenBlock, vineBlock);
            //   let face = getFaceFromBlocks(event.block, event.player.getBlockFromViewDirection().block);
            // 4. Map that face to your vine‐state key
            const faceToStateProp = {
              up: "hb_hr:floor_vine",
              south: "hb_hr:north_vine",
              west: "hb_hr:east_vine",
              north: "hb_hr:south_vine",
              east: "hb_hr:west_vine",
              // we ignore "down" here, or you could map it if desired
            };
            const stateKey = faceToStateProp[face];
            if (!stateKey) {
              //world.sendMessage("return statekey err");
              // clicked the bottom face, or something unmapped
              return;
            }
            event.block.setType("hb_hr:cursed_vine_new");
            const newVine = event.block;
            //world.sendMessage("newvbine: " + newVine.typeId);
            // 5. Pull current permutation, flip only that face’s state to true
            const perm = newVine.permutation;
            const newStates = {
              "hb_hr:floor_vine": event.brokenBlockPermutation.getState("hb_hr:floor_vine"),
              "hb_hr:north_vine": event.brokenBlockPermutation.getState("hb_hr:north_vine"),
              "hb_hr:east_vine": event.brokenBlockPermutation.getState("hb_hr:east_vine"),
              "hb_hr:south_vine": event.brokenBlockPermutation.getState("hb_hr:south_vine"),
              "hb_hr:west_vine": event.brokenBlockPermutation.getState("hb_hr:west_vine"),
            };
            newStates[stateKey] = false;
            // 6. Apply the updated permutation
            const newPerm = BlockPermutation.resolve(event.block.typeId, newStates);
            newVine.setPermutation(newPerm);

            // const player = event.player;
            // const dim = player.dimension;
            // const clickedLoc = event.block.location; // BlockLocation des gesetzten Blocks
            // // Blickrichtung berechnen
            // const rot = player.getRotation(); // { x:pitch, y:yaw, z:roll? }
            // const yawRad = rot.y * (Math.PI / 180);
            // const pitchRad = rot.x * (Math.PI / 180);
            // const dir = { x: -Math.sin(yawRad) * Math.cos(pitchRad), y: -Math.sin(pitchRad), z: Math.cos(yawRad) * Math.cos(pitchRad) };
            // //world.sendMessage(dir.x.toString());
            // //world.sendMessage(dir.y.toString());
            // //world.sendMessage(dir.z.toString());
            // const face = faceFromDirection(dir);
            // //world.sendMessage(face);
            // const oppFace = face;
            // const behindLoc = { x: clickedLoc.x + dir.x, y: clickedLoc.y + dir.y, z: clickedLoc.z + dir.z };
            // //world.sendMessage(behindLoc.x.toString());
            // //world.sendMessage(behindLoc.y.toString());
            // //world.sendMessage(behindLoc.z.toString());
            // const behindBlock = dim.getBlock(behindLoc);
            // player.teleport(behindLoc);
            // behindBlock.above().setType("diamond_block");
          }
        }

        // (optional) debug print
        // //world.sendMessage(`Set ${stateKey} via face “${face}”`);

        // // event.block.setType("dirt");
        // //world.sendMessage("break side vine and set block ");
        // }
      } else {
        //world.sendMessage("check vines aroudn");
      }
    });
  }

  spawnItemFromBlock(player, block, SpawnItemName) {
    // //world.sendMessage("spawn 3");
    let blockItem = new ItemStack(SpawnItemName);
    world.getDimension(player.dimension.id).spawnItem(blockItem, block.location);
  }
}

export function vineCheckBlockBelow(block) {
  if (block.below().typeId == "minecraft:air" || block.below().typeId == "hb_hr:hive_carpet" || block.below().typeId == "minecraft:structure_void" || block.below().typeId == "hb_hr:small_hive_egg" || block.below().typeId == "hb_hr:large_hive_egg") {
    if (block.permutation.getState("hb_hr:full_block") == false) return;
    const newPermutationAbove = BlockPermutation.resolve(block.typeId, {
      "minecraft:block_face": block.permutation.getState("minecraft:block_face"),
      "hb_hr:full_block": false,
    });
    block.setPermutation(newPermutationAbove);
  }
}

export function breakVines(block) {
  // if (block.typeId == "hb_hr:cursed_vine_new" && block.above().typeId == "minecraft:air") {
  //   block.dimension.runCommand("/fill " + block.location.x + " " + block.location.y + " " + block.location.z + " " + block.location.x + " " + block.location.y + " " + block.location.z + " air destroy");
  // }
  if (block.typeId == "minecraft:air" && block.above().typeId == "hb_hr:cursed_vine_new") {
    // If the event block is air and the block above is a hive vine, update the above block's permutation.
    const newPermutationAbove = BlockPermutation.resolve("hb_hr:cursed_vine_new", {
      "minecraft:block_face": block.above().permutation.getState("minecraft:block_face"),
      "hb_hr:full_block": false,
    });
    block.above().setPermutation(newPermutationAbove);
  }
}

function destroyAllSideVines(player, startBlock) {
  //world.sendMessage("destroy all side vines to the bottom besides there the floor vines");
}
function destroySingleSideVines(player, startBlock, directionToDestroy) {
  // Cast a ray downward from the event block to find the last vine block.
  let currentBlock = startBlock;
  if (currentBlock.below().typeId == "hb_hr:cursed_vine_new") {
    destroySingleSideVines(player, currentBlock.below(), directionToDestroy);
  }
  if (currentBlock.typeId == "hb_hr:cursed_vine_new") {
    if (checkBlockBehindVineBlock(player, currentBlock, directionToDestroy) == false) {
      //world.sendMessage("STOP BREAKING");
      return;
    }
    const perm = currentBlock.permutation;
    //world.sendMessage("current: +++++++" + currentBlock.typeId);
    //world.sendMessage("abovew: +++++++" + currentBlock.above().typeId);

    if (currentBlock.above().typeId == "hb_hr:cursed_vine_new") {
      //world.sendMessage("######cursed_vine above");
      return;
    }
    if (currentBlock.above().typeId == "minecraft:air") {
      // currentBlock.setType("dirt");
      //world.sendMessage("####air above");
      // list out all five possible vine‐states
      const dirs = ["hb_hr:floor_vine", "hb_hr:north_vine", "hb_hr:east_vine", "hb_hr:south_vine", "hb_hr:west_vine"];
      const newStates = dirs.reduce((map, dir) => {
        const key = dir;
        // if this is the side to destroy, always false, otherwise keep old
        map[key] = dir === directionToDestroy ? false : perm.getState(key);
        return map;
      }, {});
      // 6. Apply the updated permutation
      try {
        const newPerm = BlockPermutation.resolve(currentBlock.typeId, newStates);
        currentBlock.setPermutation(newPerm);
        //world.sendMessage("sssssssssabove " + currentBlock.typeId.toString());
        // currentBlock.setType("dirt");
        // check block behind if that is solid then break
        destroyVineWithZeroVineStates(player, currentBlock, directionToDestroy);
      } catch (error) {
        //world.sendMessage(directionToDestroy + " ERRRR########");
        // currentBlock.setType("gold_block");
        player.dimension.runCommand("/fill " + currentBlock.location.x + " " + currentBlock.location.y + " " + currentBlock.location.z + " " + currentBlock.location.x + " " + currentBlock.location.y + " " + currentBlock.location.z + " air destroy");
      }
    }
  }
}

function checkBlockBehindVineBlock(player, block, directionToDestroy) {
  // 1) extract e.g. "west" from "hb_hr:west_vine"
  //    split off the namespace, then strip the "_vine" suffix
  const [, rawDir] = directionToDestroy.split(":"); // ["hb_hr","west_vine"]
  const dirName = rawDir.replace("_vine", ""); // "west"

  // 2) map each direction name to a vector offset
  const dirVectors = {
    north: { x: 0, y: 0, z: -1 },
    south: { x: 0, y: 0, z: 1 },
    west: { x: -1, y: 0, z: 0 },
    east: { x: 1, y: 0, z: 0 },
    up: { x: 0, y: 1, z: 0 },
    down: { x: 0, y: -1, z: 0 },
  };

  const vec = dirVectors[dirName];
  if (!vec) {
    //world.sendMessage("no VINES HERE");
    // unrecognized direction—debug message
    // player.dimension.runCommand(`say §cUnknown vine‐direction '${dirName}'`);
    return;
  }

  // 3) compute the target position one block “behind” in that direction
  const behindPos = { x: block.location.x + vec.x, y: block.location.y + vec.y, z: block.location.z + vec.z };

  // 4) fetch that block and, if it’s air, destroy it
  const dim = player.dimension;
  const behindBlock = dim.getBlock(behindPos);
  //world.sendMessage("BLOCK BEHIND IS: " + behindBlock.typeId);
  if (behindBlock.typeId != "minecraft:air") {
    //world.sendMessage("block behind is no air");
    return false;
  } else {
    //world.sendMessage("block behind is  air");
    return true;
  }
}
function destroyVineWithZeroVineStates(player, block, directionToDestroy) {
  const perm = block.permutation;
  const allStates = perm.getAllStates();
  let counter = 0;
  // 2) Or using a for…of loop:
  for (const [key, value] of Object.entries(allStates)) {
    //world.sendMessage(key + "=" + value);
    if (key.includes("_vine") && value == true) {
      counter++;
    }
  }
  if (counter === 0) {
    // 1) extract e.g. "west" from "hb_hr:west_vine"
    //    split off the namespace, then strip the "_vine" suffix
    const [, rawDir] = directionToDestroy.split(":"); // ["hb_hr","west_vine"]
    const dirName = rawDir.replace("_vine", ""); // "west"

    // 2) map each direction name to a vector offset
    const dirVectors = {
      north: { x: 0, y: 0, z: -1 },
      south: { x: 0, y: 0, z: 1 },
      west: { x: -1, y: 0, z: 0 },
      east: { x: 1, y: 0, z: 0 },
      up: { x: 0, y: 1, z: 0 },
      down: { x: 0, y: -1, z: 0 },
    };

    const vec = dirVectors[dirName];
    if (!vec) {
      //world.sendMessage("no VINES HERE");
      // unrecognized direction—debug message
      // player.dimension.runCommand(`say §cUnknown vine‐direction '${dirName}'`);
      return;
    }

    // 3) compute the target position one block “behind” in that direction
    const behindPos = { x: block.location.x + vec.x, y: block.location.y + vec.y, z: block.location.z + vec.z };

    // 4) fetch that block and, if it’s air, destroy it
    const dim = player.dimension;
    const behindBlock = dim.getBlock(behindPos);
    //world.sendMessage;

    system.runTimeout(() => {
      if (behindBlock.typeId === "minecraft:air") {
        //world.sendMessage("air");
        player.dimension.runCommand("/fill " + block.location.x + " " + block.location.y + " " + block.location.z + " " + block.location.x + " " + block.location.y + " " + block.location.z + " air destroy");
        //world.sendMessage("##############above " + block.above().typeId);
        //world.sendMessage("##############current " + block.typeId);
        // destroys the air block (no-op) but clears any tile entity/etc.
        // dim.runCommand(`/fill ${behindPos.x} ${behindPos.y} ${behindPos.z} ` + `${behindPos.x} ${behindPos.y} ${behindPos.z} air destroy`);
      } else {
        //world.sendMessage("full block ");
        //world.sendMessage("##############above " + block.above().typeId);
        //world.sendMessage("##############current " + block.typeId);
      }
    }, 5);
  }
}

function destroySideVines(player, startBlock) {
  // Cast a ray downward from the event block to find the last vine block.
  const lastVineBlock = player.dimension.getBlockFromRay(
    startBlock.location,
    { x: 0, y: -100, z: 0 },
    {
      excludeTypes: ["hb_hr:cursed_vine_new"],
    }
  );

  // Create a volume from the event block's location to the last vine block's location.
  const volume = new BlockVolume({ x: startBlock.location.x, y: startBlock.location.y, z: startBlock.location.z }, { x: startBlock.location.x, y: lastVineBlock.block.location.y + 1, z: startBlock.location.z });

  // Iterate over each block location in the volume and replace the block with air.
  const locations = volume.getBlockLocationIterator();
  for (const location of locations) {
    const vineBlock = player.dimension.getBlock(location);
    player.dimension.runCommand("/fill " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " air destroy");
  }
}

function initDestroySideVines(player, block) {
  const northBlock = block.north();
  const southBlock = block.south();
  const eastBlock = block.east();
  const westBlock = block.west();
  if (northBlock && northBlock.typeId == "hb_hr:cursed_vine_new") destroySideVines(player, northBlock);
  if (southBlock && southBlock.typeId == "hb_hr:cursed_vine_new") destroySideVines(player, southBlock);
  if (eastBlock && eastBlock.typeId == "hb_hr:cursed_vine_new") destroySideVines(player, eastBlock);
  if (westBlock && westBlock.typeId == "hb_hr:cursed_vine_new") destroySideVines(player, westBlock);
  player.dimension.runCommand("/fill " + block.location.x + " " + block.location.y + " " + block.location.z + " " + block.location.x + " " + block.location.y + " " + block.location.z + " air destroy");
}

function checkForCursedVinesAndChangeStates(testblock) {
  // for each of the four horizontal directions...
  const brokenBlock = testblock;
  //world.sendMessage(brokenBlock.typeId);
  const neighbors = [
    { dir: "south", block: brokenBlock.north() },
    { dir: "north", block: brokenBlock.south() },
    { dir: "west", block: brokenBlock.east() },
    { dir: "east", block: brokenBlock.west() },
  ];

  for (const { dir, block } of neighbors) {
    if (!block) continue;
    // only touch your cursed-vine blocks
    if (block.typeId === "hb_hr:cursed_vine_new") {
      //world.sendMessage("VINE HERE");
      removeVineAttachment(block, dir);
    }
  }
  // //world.sendMessage(" sdasad");
  // const northBlock = block.north();
  // const southBlock = block.south();
  // const eastBlock = block.east();
  // const westBlock = block.west();
  // if (northBlock) updateNearbyCursedVine(player, northBlock);
  // if (southBlock) updateNearbyCursedVine(player, southBlock);
  // if (eastBlock) updateNearbyCursedVine(player, eastBlock);
  // if (westBlock) updateNearbyCursedVine(player, westBlock);
}

// 2) Turn off the single face on the neighbour
function removeVineAttachment(block, brokenSide) {
  // pull out all five vine-states
  const perm = block.permutation;
  const states = {
    "hb_hr:floor_vine": perm.getState("hb_hr:floor_vine"),
    "hb_hr:north_vine": perm.getState("hb_hr:north_vine"),
    "hb_hr:east_vine": perm.getState("hb_hr:east_vine"),
    "hb_hr:south_vine": perm.getState("hb_hr:south_vine"),
    "hb_hr:west_vine": perm.getState("hb_hr:west_vine"),
  };

  // flip off the one corresponding to the broken side
  // e.g. if we’re updating the block north of the break, brokenSide === "north"
  states[`hb_hr:${brokenSide}_vine`] = false;

  // build and apply the new permutation
  const newPerm = BlockPermutation.resolve(block.typeId, states);
  block.setPermutation(newPerm);
}

function getAdjacentBlock(baseBlock, blockFace, reverse = false) {
  // 1. Normalize the face string: "West" → "west"
  const face = blockFace.charAt(0).toLowerCase() + blockFace.slice(1);

  // 2. Mappings for offsets and opposites
  const offsets = {
    north: { x: 0, y: 0, z: -1 },
    south: { x: 0, y: 0, z: 1 },
    east: { x: 1, y: 0, z: 0 },
    west: { x: -1, y: 0, z: 0 },
    up: { x: 0, y: 1, z: 0 },
    down: { x: 0, y: -1, z: 0 },
  };
  const opposite = {
    north: "south",
    south: "north",
    east: "west",
    west: "east",
    up: "down",
    down: "up",
  };

  // 3. Decide which direction we actually want
  const dir = reverse ? opposite[face] || face : face;

  // //world.sendMessage("dir:" + dir);

  // 4. Look up the offset vector
  const off = offsets[dir];
  if (!off) {
    // console.warn(`Unknown face "${blockFace}" → "${dir}"`);
    return null;
  }

  // 5. Compute the target location and grab that block
  const loc = baseBlock.location;
  const targetLoc = {
    x: loc.x + off.x,
    y: loc.y + off.y,
    z: loc.z + off.z,
  };
  return baseBlock.dimension.getBlock(targetLoc);
}

function checkIfVineNeedsToBreak(vineBlock, brokenBlock) {
  //world.sendMessage("START BREAK FIRST BLOCK");
  const allStates = vineBlock.permutation.getAllStates();
  let counter = 0;
  let directionArray = [];
  //world.sendMessage(allStates.toString());
  for (const [key, value] of Object.entries(allStates)) {
    //world.sendMessage(key + "=" + value);
    if (key.includes("_vine") && value == true) {
      directionArray.push(key);
      counter++;
    }
  }
  let face = getFaceFromBlocks(brokenBlock, vineBlock);
  if (vineBlock.above().typeId != "hb_hr:cursed_vine_new") {
    //world.sendMessage("remove this vine face because above isnt any other vine block");

    //world.sendMessage("COUINTER: " + counter.toString());
    // only one vine is inside the block active so detroy the block
    if (counter == 0) {
      system.runTimeout(() => {
        if (vineBlock.below().typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreakWithDirection(vineBlock.below(), brokenBlock.below(), face);
      }, 5);
    }
    if (counter == 1) {
      if (!directionArray[0].includes("floor")) {
        //world.sendMessage("break full block");
        vineBlock.dimension.runCommand("/fill " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " air destroy");
        //world.sendMessage("2CHECK HERE FOR MORE VINES BLEOW in direction: " + face);
        system.runTimeout(() => {
          if (vineBlock.below().typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreakWithDirection(vineBlock.below(), brokenBlock.below(), face);
        }, 5);
      }
      // else destroyAllSideVines(player, event.block);
    } else {
      // 1. Grab the two block positions

      // 4. Map that face to your vine‐state key
      const faceToStateProp = {
        up: "hb_hr:floor_vine",
        south: "hb_hr:north_vine",
        west: "hb_hr:east_vine",
        north: "hb_hr:south_vine",
        east: "hb_hr:west_vine",
        // we ignore "down" here, or you could map it if desired
      };

      const stateKey = faceToStateProp[face];
      if (!stateKey) {
        //world.sendMessage("return statekey err");
        // clicked the bottom face, or something unmapped
        return;
      }

      // 5. Pull current permutation, flip only that face’s state to true
      const perm = vineBlock.permutation;
      const newStates = {
        "hb_hr:floor_vine": perm.getState("hb_hr:floor_vine"),
        "hb_hr:north_vine": perm.getState("hb_hr:north_vine"),
        "hb_hr:east_vine": perm.getState("hb_hr:east_vine"),
        "hb_hr:south_vine": perm.getState("hb_hr:south_vine"),
        "hb_hr:west_vine": perm.getState("hb_hr:west_vine"),
      };
      newStates[stateKey] = false;

      // 6. Apply the updated permutation
      const newPerm = BlockPermutation.resolve(vineBlock.typeId, newStates);
      vineBlock.setPermutation(newPerm);

      // (optional) debug print
      //world.sendMessage(`Set ${stateKey} via face “${face}”`);

      // event.block.setType("dirt");
      //world.sendMessage("break side vine and set block ");
      system.runTimeout(() => {
        if (vineBlock.below().typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreakWithDirection(vineBlock.below(), brokenBlock.below(), face);
      }, 5);
    }
    //world.sendMessage("111CHECK HERE FOR MORE VINES BLEOW in direction: " + face);
  } else {
    //world.sendMessage("sssssssabove is vine block");
    return;
  }
}
function checkIfTopVineNeedsToBreak(vineBlock, brokenBlock) {
  //world.sendMessage("START BREAK FIRST TOP BLOCK");
  const allStates = vineBlock.permutation.getAllStates();
  let counter = 0;
  let directionArray = [];
  //world.sendMessage(allStates.toString());
  for (const [key, value] of Object.entries(allStates)) {
    //world.sendMessage(key + "=" + value);
    if (key.includes("_vine") && value == true) {
      directionArray.push(key);
      counter++;
    }
  }
  let face = getFaceFromBlocks(brokenBlock, vineBlock);
  if (vineBlock.above().typeId != "hb_hr:cursed_vine_new") {
    //world.sendMessage("remove this vine face because above isnt any other vine block");

    //world.sendMessage("COUINTER: " + counter.toString());
    // only one vine is inside the block active so detroy the block
    if (counter == 1) {
      if (!directionArray[0].includes("floor")) {
        //world.sendMessage("break full block");
        vineBlock.dimension.runCommand("/fill " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " air destroy");
        //world.sendMessage("2CHECK HERE FOR MORE VINES BLEOW in direction: " + face);
        system.runTimeout(() => {
          if (vineBlock.below().typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreakWithDirection(vineBlock.below(), brokenBlock.below(), face);
        }, 5);
      }
      // else destroyAllSideVines(player, event.block);
    } else {
      //world.sendMessage("SET PERM FOR TOP BLOCK");
      // 1. Grab the two block positions

      // 5. Pull current permutation, flip only that face’s state to true
      const perm = vineBlock.permutation;
      const newStates = {
        "hb_hr:floor_vine": false,
        "hb_hr:north_vine": perm.getState("hb_hr:north_vine"),
        "hb_hr:east_vine": perm.getState("hb_hr:east_vine"),
        "hb_hr:south_vine": perm.getState("hb_hr:south_vine"),
        "hb_hr:west_vine": perm.getState("hb_hr:west_vine"),
      };

      // 6. Apply the updated permutation
      const newPerm = BlockPermutation.resolve(vineBlock.typeId, newStates);
      vineBlock.setPermutation(newPerm);

      // event.block.setType("dirt");
      //world.sendMessage("break side vine and set block ");
      system.runTimeout(() => {
        if (vineBlock.below().typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreakWithDirection(vineBlock.below(), brokenBlock.below(), face);
      }, 5);
    }
    //world.sendMessage("111CHECK HERE FOR MORE VINES BLEOW in direction: " + face);
  } else {
    //world.sendMessage("SET PERM FOR TOP BLOCK");
    // 1. Grab the two block positions

    // 5. Pull current permutation, flip only that face’s state to true
    const perm = vineBlock.permutation;
    const newStates = {
      "hb_hr:floor_vine": false,
      "hb_hr:north_vine": perm.getState("hb_hr:north_vine"),
      "hb_hr:east_vine": perm.getState("hb_hr:east_vine"),
      "hb_hr:south_vine": perm.getState("hb_hr:south_vine"),
      "hb_hr:west_vine": perm.getState("hb_hr:west_vine"),
    };

    // 6. Apply the updated permutation
    const newPerm = BlockPermutation.resolve(vineBlock.typeId, newStates);
    vineBlock.setPermutation(newPerm);

    // event.block.setType("dirt");
    //world.sendMessage("break side vine and set block ");
    //world.sendMessage("sssssssabove is vine block");
    return;
  }
}
function checkIfVineNeedsToBreakWithDirection(vineBlock, brokenBlock, VineFaceFromAboveBlock) {
  //world.sendMessage("START BREAK SECOND AND MORE BLOCK");
  if (vineBlock.above().typeId != "hb_hr:cursed_vine_new") {
    //world.sendMessage("remove this vine face because above isnt any other vine block");
    const allStates = vineBlock.permutation.getAllStates();
    let counter = 0;
    let directionArray = [];
    //world.sendMessage(allStates.toString());
    for (const [key, value] of Object.entries(allStates)) {
      //world.sendMessage(key + "=" + value);
      if (key.includes("_vine") && value == true) {
        directionArray.push(key);
        counter++;
      }
    }

    let face = getFaceFromBlocks(brokenBlock, vineBlock);
    //world.sendMessage("COUINTER: " + counter.toString());
    // only one vine is inside the block active so detroy the block
    if (counter == 1) {
      //world.sendMessage(directionArray[0] + "#######");
      if (!directionArray[0].includes("floor")) {
        //world.sendMessage("break full block");
        vineBlock.dimension.runCommand("/fill " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " air destroy");
        //world.sendMessage("with direction 2CHECK HERE FOR MORE VINES BLEOW in direction: " + VineFaceFromAboveBlock);
        system.runTimeout(() => {
          if (vineBlock.below().typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreakWithDirection(vineBlock.below(), brokenBlock.below(), VineFaceFromAboveBlock);
        }, 5);
      }
      return;
      // else destroyAllSideVines(player, event.block);
    } else {
      // 1. Grab the two block positions

      // 4. Map that face to your vine‐state key
      const faceToStateProp = {
        up: "hb_hr:floor_vine",
        south: "hb_hr:north_vine",
        west: "hb_hr:east_vine",
        north: "hb_hr:south_vine",
        east: "hb_hr:west_vine",
        // we ignore "down" here, or you could map it if desired
      };

      const stateKey = faceToStateProp[face];
      if (!stateKey) {
        //world.sendMessage("return statekey err");
        // clicked the bottom face, or something unmapped
        return;
      }

      // 5. Pull current permutation, flip only that face’s state to true
      const perm = vineBlock.permutation;
      for (const [key, value] of Object.entries(allStates)) {
        //world.sendMessage(key + "=########" + value);
      }
      const newStates = {
        "hb_hr:floor_vine": perm.getState("hb_hr:floor_vine"),
        "hb_hr:north_vine": perm.getState("hb_hr:north_vine"),
        "hb_hr:east_vine": perm.getState("hb_hr:east_vine"),
        "hb_hr:south_vine": perm.getState("hb_hr:south_vine"),
        "hb_hr:west_vine": perm.getState("hb_hr:west_vine"),
      };
      newStates[stateKey] = false;

      // 6. Apply the updated permutation
      const newPerm = BlockPermutation.resolve(vineBlock.typeId, newStates);
      vineBlock.setPermutation(newPerm);

      // (optional) debug print
      //world.sendMessage(`Set ${stateKey} via face “${face}”`);

      // event.block.setType("dirt");
      //world.sendMessage("break side vine and set block ");
      //world.sendMessage("with direction1CHECK HERE FOR MORE VINES BLEOW in direction: " + face);
    }
    // system.runTimeout(() => {
    //   if (vineBlock.below().typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreakWithDirection(vineBlock.below(), brokenBlock.below(), face);
    // }, 5);
  } else {
    //world.sendMessage("above is vine block");
    const allStates = vineBlock.permutation.getAllStates();
    let counter = 0;
    let directionArray = [];
    //world.sendMessage(allStates.toString());
    for (const [key, value] of Object.entries(allStates)) {
      //world.sendMessage(key + "=ddd" + value);
      if (key.includes("_vine") && value == true) {
        directionArray.push(key);
        counter++;
      }
    }

    //world.sendMessage("COUINTER:sss" + counter);
    //world.sendMessage(directionArray[0]);
    //world.sendMessage(swapDirection(VineFaceFromAboveBlock));
    // if (!directionArray[0].includes("floor") && directionArray.includes(swapDirection(VineFaceFromAboveBlock))) {
    // if (directionArray.includes(swapDirection(VineFaceFromAboveBlock))) {
    if (directionArray.some((entry) => entry.includes(swapDirection(VineFaceFromAboveBlock)))) {
      //world.sendMessage("DETECTED VINE FACE FROM ABOVE");

      if (counter == 1) {
        if (!directionArray[0].includes("floor")) {
          //world.sendMessage("with directionbreak full block");
          vineBlock.dimension.runCommand("/fill " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " air destroy");
        }
        // else destroyAllSideVines(player, event.block);
      } else {
        if (!checkBlockBehindVineBlock) {
          //world.sendMessage("NO AIR HERE RETURN");
        } else {
          //world.sendMessage("AIR HERE GO ON");
        }
        //world.sendMessage("REMOVE HERE SIDE");
        // 1. Grab the two block positions

        // 4. Map that face to your vine‐state key
        const faceToStateProp = {
          up: "hb_hr:floor_vine",
          south: "hb_hr:north_vine",
          west: "hb_hr:east_vine",
          north: "hb_hr:south_vine",
          east: "hb_hr:west_vine",
          // we ignore "down" here, or you could map it if desired
        };

        const stateKey = faceToStateProp[VineFaceFromAboveBlock];
        if (!stateKey) {
          //world.sendMessage("return statekey err");
          // clicked the bottom face, or something unmapped
          return;
        }

        // 5. Pull current permutation, flip only that face’s state to true
        const perm = vineBlock.permutation;
        const newStates = {
          "hb_hr:floor_vine": perm.getState("hb_hr:floor_vine"),
          "hb_hr:north_vine": perm.getState("hb_hr:north_vine"),
          "hb_hr:east_vine": perm.getState("hb_hr:east_vine"),
          "hb_hr:south_vine": perm.getState("hb_hr:south_vine"),
          "hb_hr:west_vine": perm.getState("hb_hr:west_vine"),
        };
        newStates[stateKey] = false;

        for (const [key, value] of Object.entries(newStates)) {
          //world.sendMessage(key + "=ssssddd" + value);
        }

        // 6. Apply the updated permutation
        const newPerm = BlockPermutation.resolve(vineBlock.typeId, newStates);
        vineBlock.setPermutation(newPerm);

        // (optional) debug print
        //world.sendMessage(`Set ${stateKey} via face “${VineFaceFromAboveBlock}”`);

        // event.block.setType("dirt");
        //world.sendMessage("break side vine and set block ");
      }

      // vineBlock.dimension.runCommand("/fill " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " air destroy");
      // //world.sendMessage("2CHECK HERE FOR MORE VINES BLEOW in direction: " + face);
      system.runTimeout(() => {
        if (vineBlock.below().typeId == "hb_hr:cursed_vine_new") checkIfVineNeedsToBreakWithDirection(vineBlock.below(), brokenBlock.below(), VineFaceFromAboveBlock);
      }, 5);
    } else {
      //world.sendMessage("err1");
    }
    // else destroyAllSideVines(player, event.block);

    return;
  }
}

function getFaceFromBlocks(baseBlock, hitBlock) {
  const { x: bx, y: by, z: bz } = baseBlock.location;
  const { x: hx, y: hy, z: hz } = hitBlock.location;
  const dx = hx - bx;
  const dy = hy - by;
  const dz = hz - bz;

  if (dx === 1 && dy === 0 && dz === 0) return "east";
  if (dx === -1 && dy === 0 && dz === 0) return "west";
  if (dx === 0 && dy === 1 && dz === 0) return "up";
  if (dx === 0 && dy === -1 && dz === 0) return "down";
  if (dx === 0 && dy === 0 && dz === 1) return "south";
  if (dx === 0 && dy === 0 && dz === -1) return "north";
  return null;
}

function swapDirection(dir) {
  const map = {
    north: "south",
    south: "north",
    east: "west",
    west: "east",
  };
  const key = dir.toLowerCase();
  if (!(key in map)) {
    throw new Error(`unknown direction: ${dir}`);
  }
  const swapped = map[key];
  return /^[A-Z]/.test(dir) ? swapped.charAt(0).toUpperCase() + swapped.slice(1) : swapped;
}

function faceFromDirection(dir) {
  const ax = Math.abs(dir.x),
    ay = Math.abs(dir.y),
    az = Math.abs(dir.z);
  if (ax > ay && ax > az) return dir.x > 0 ? "east" : "west";
  if (ay > az) return dir.y > 0 ? "up" : "down";
  return dir.z > 0 ? "south" : "north";
}
