import * as mc from "@minecraft/server";
import * as vector from "./utils/vector";
import * as structureManager from "./structure/structureManager";
import * as selectors from "./utils/selectors";

const poolManager = {
  /**
   *
   * @param {String} pool
   * @param {Number} rot
   * @param {mc.Block} block
   * @param {mc.Entity} entity
   * @returns
   */
  getRandom(pool, rot, block, rotItem, offset, entity) {
    let newRot = rot ?? 0;

    let index = Math.floor(Math.random() * this[pool].length);

    if (pool === `path_pool`) {
      const topSolidBlock = block.dimension.getTopmostBlock(vector.getBlockLocalCoord(block, { x: 0, y: 0, z: 1 }), block.dimension.heightRange.max);
      const height = topSolidBlock.location.y - block.location.y;
      const blockList = structureBlockList();
      const maxDistance = 8;

      for (let offsetZ = 1; offsetZ <= maxDistance; offsetZ++) {
        const checkPosition = vector.getBlockLocalCoord(block, { x: 0, y: 0, z: offsetZ });
        const topSolidBlock2 = block.dimension.getTopmostBlock(checkPosition, block.dimension.heightRange.max);

        if (blockList.includes(topSolidBlock2.typeId)) {
          return {
            structure: mc.world.structureManager.get("hf_mzs/monastery/monastery_wall_connector_end"),
            name: "hf_mzs/monastery/monastery_wall_connector_end",
            rot: Number(newRot),
            offset: vector.add(offset, { x: 0, y: 0, z: -1 }),
          };
        }
      }

      if (Math.abs(height) >= 10) {
        return poolManager.getRandom("tower_pool", 0, block, rotItem + 180, offset, entity);
      }

      if (Math.abs(height) < 10) {
        const random = Math.random();
        if (random >= 0.7) {
          return poolManager.getRandom("wall_pool", 0, block, rotItem, offset, entity);
        } else if (random >= 0.6 && random < 0.7) {
          return poolManager.getRandom("center_corners_pool", 180, block, rotItem, { x: 0, y: 0, z: -1 }, entity);
        } else if (random < 0.6) {
          const blockList = structureBlockList();
          if (blockList.includes(topSolidBlock.typeId)) {
            return poolManager.getRandom("wall_pool", 0, block, rotItem, offset, entity);
          } else {
            const random2 = Math.random();
            if (random2 >= 0.65) {
              mc.system.runTimeout(() => {
                return poolManager.getRandom("room_pool", 0, block, rotItem + 270, { x: 3, y: 0, z: -3 }, entity);
              }, 5);
            } else if (random2 < 0.65) {
              return poolManager.getRandom("tower_pool", 0, block, rotItem + 180, offset, entity);
            }
          }
        }
      }
    } else if (pool === `wall_pool`) {
      const random = Math.random();
      if (random >= 0.6) {
        return poolManager.getRandom("center_walls_pool", 0, block, rotItem, offset, entity);
      } else if (random < 0.6) {
        return poolManager.getRandom("wall_gap_pool", 0, block, rotItem, offset, entity);
      }
    } else if (pool === `tower_pool`) {
      let type = "";
      const randomType = Math.random();
      if (randomType > 0.5) {
        type = "hf_mzs:library";
      } else {
        type = "hf_mzs:storage";
      }

      const topSolidBlock = block.dimension.getTopmostBlock(vector.getBlockLocalCoord(block, { x: 0, y: 0, z: 3 }), block.dimension.heightRange.max);
      const height = topSolidBlock.location.y - block.location.y;
      //mc.world.sendMessage(`${height} ${topSolidBlock.typeId} ${JSON.stringify(vector.getBlockLocalCoord(block, {x: 0, y: 0, z: 1}))}`)

      if (height >= -10) {
        let structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_base");
        const blockRotation = block.permutation.getState("facing_direction");
        const structureLoc = structurePos(structure, blockRotation, rotItem, 0, offset);
        let start = {
          x: block.location.x + structureLoc.xOff,
          y: block.location.y + structureLoc.yOff,
          z: block.location.z + structureLoc.zOff,
        };
        const rotName = structureManager.toStructureRot.get(structureLoc.rot);

        mc.world.structureManager.place(structure, block.dimension, start, {
          animationMode: mc.StructureAnimationMode.None,
          rotation: rotName,
          includeEntities: true,
        });
        block.dimension.runCommand(
          `/tag @e[type=hf_mzs:custom_jigsaw_util,tag=!hf_mzs:origin,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:origin`
        );
        block.dimension.runCommand(
          `/tag @e[type=hf_mzs:custom_jigsaw_util,tag=!hf_mzs:origin,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:base`
        );
        mc.system.run(() => {
          block.dimension.runCommand(
            `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
          );
          block.dimension.runCommand(
            `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:base`
          );
          start.y += 5;
          putTop();
          function putTop() {
            start.y += 6;
            const topSolidBlock = block.dimension.getTopmostBlock(start, block.dimension.heightRange.max);
            const height = topSolidBlock.location.y - start.y;
            if (height >= 3) {
              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_middle");
              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y - 4},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z
                }] add ${type}`
              );

              putTop();
            } else {
              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_top");
              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y - 4},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z
                }] add ${type}`
              );

              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_roof");
              const newOffset = roofOffset(blockRotation);
              start.x += newOffset.xOff;
              start.y += 4;
              start.z += newOffset.zOff;

              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
            }
          }
        });
      } else {
        let structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_top");
        const blockRotation = block.permutation.getState("facing_direction");
        let structureLoc = structurePos(structure, blockRotation, rotItem, 0, offset);
        let start = {
          x: block.location.x + structureLoc.xOff,
          y: block.location.y + structureLoc.yOff + 5,
          z: block.location.z + structureLoc.zOff,
        };
        const rotName = structureManager.toStructureRot.get(structureLoc.rot);

        mc.world.structureManager.place(structure, block.dimension, start, {
          animationMode: mc.StructureAnimationMode.None,
          rotation: rotName,
          includeEntities: true,
        });
        block.dimension.runCommand(
          `/tag @e[type=hf_mzs:custom_jigsaw_util,tag=!hf_mzs:origin,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:origin`
        );
        structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_roof");
        const newOffset = roofOffset(blockRotation);
        start.x += newOffset.xOff;
        start.y += 4;
        start.z += newOffset.zOff;
        mc.world.structureManager.place(structure, block.dimension, start, {
          animationMode: mc.StructureAnimationMode.None,
          rotation: rotName,
          includeEntities: true,
        });
        mc.system.run(() => {
          block.dimension.runCommand(
            `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y - 4},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
          );
          start.x -= newOffset.xOff;
          start.y -= 4;
          start.z -= newOffset.zOff;
          putBase();
          function putBase() {
            start.y -= 6;
            const topSolidBlock = block.dimension.getTopmostBlock(start, start.y);
            const height = topSolidBlock.location.y - start.y;
            if (height <= -10) {
              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_middle");
              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
              );

              putBase();
            } else {
              start.y -= 5;
              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_base");
              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
              );
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:base`
              );
            }
          }
        });
      }
    } else if (pool === `tower_path_pool`) {
      const tag = entity.getTags()[0];
      if (tag !== `hf_mzs:origin`) {
        const blockList = structureBlockList();
        const maxDistance = 15;

        for (let offsetZ = 7; offsetZ <= maxDistance; offsetZ++) {
          const checkPosition = vector.getBlockLocalCoord(block, { x: 0, y: 0, z: offsetZ });
          const topSolidBlock = block.dimension.getTopmostBlock(checkPosition, block.dimension.heightRange.max);
          const height = topSolidBlock.location.y - block.location.y;

          if (blockList.includes(topSolidBlock.typeId) || Math.abs(height) >= 20) {
            //mc.world.sendMessage(`${topSolidBlock.typeId} ${height} ${JSON.stringify(topSolidBlock.location)}`)
            return poolManager.getRandom("windows_pool", 0, block, rotItem, offset, entity);
          }
        }

        const random = Math.random();
        if (random >= 0.6) {
          return poolManager.getRandom("for_tower_path_pool", 0, block, rotItem, offset, entity);
        } else {
          return poolManager.getRandom("windows_pool", 0, block, rotItem, offset, entity);
        }
      } else {
        return poolManager.getRandom("windows_pool", 0, block, rotItem, offset, entity);
      }
    } else if (pool === `for_tower_path_pool`) {
      const random = Math.random();
      const tags = entity.getTags();
      if (random >= 0.5 && tags.includes("hf_mzs:base")) {
        breakFrontBlocks(block, 1);
        return poolManager.getRandom("tower_door_path_pool", 0, block, rotItem + 180, towerDoorOffset(), entity);
      } else {
        const random2 = Math.random();

        if (random2 >= 0.6) {
          breakFrontBlocks(block, 1);
          return poolManager.getRandom("center_walls_pool", 90, block, rotItem, vector.add(offset, { x: 0, y: -5, z: 3 }), entity);
        } else {
          breakFrontBlocks(block, 1);
          return poolManager.getRandom("room_pool", 0, block, rotItem, { x: 3, y: -5, z: 0 }, entity);
        }
      }
      function breakFrontBlocks(block, pos) {
        const posZ = pos + 1;
        const newBlock = block.dimension.getBlock(vector.getBlockLocalCoord(block, { x: 0, y: 0, z: posZ }));
        newBlock.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
        if (posZ < 3) {
          breakFrontBlocks(newBlock, posZ);
        }
      };
      function towerDoorOffset() {
        let doorOffset = { x: 0, y: -3, z: 3 };
        const blockRotation = block.permutation.getState("facing_direction");
        switch (blockRotation) {
          case 4: {
            doorOffset = { x: 1, y: -3, z: 1 };
            break;
          };
          case 5: {
            doorOffset = { x: -1, y: -3, z: 3 };
            break;
          }
        }
        return doorOffset;
      }
    } else if (pool === `windows_pool`) {
      function balconyOffset(initialCoord) {
        const blockRotation = block.permutation.getState("facing_direction");
        let balconyOffsetVal = vector.add(initialCoord, { x: 0, y: -2, z: 2 });
        if (blockRotation === 4) {
          balconyOffsetVal = vector.add(initialCoord, { x: 1, y: -2, z: 0 });
        } else if (blockRotation === 5) {
          balconyOffsetVal = vector.add(initialCoord, { x: -1, y: -2, z: 2 });
        }
        return balconyOffsetVal;
      };

      const blockFront = block.dimension.getBlock(vector.getBlockLocalCoord(block, { x: 0, y: 1, z: 3 }));
      if (!blockFront || blockFront.typeId === `minecraft:air`) {
        const random = Math.random();
        if (random >= 0.8 && !entity?.hasTag("hf_mzs:base")) {
          return { structure: mc.world.structureManager.get("hf_mzs/monastery/monastery_balcony"), name: "hf_mzs/monastery/monastery_balcony", rot: 180, offset: balconyOffset(offset) };
        } else {
          return { structure: mc.world.structureManager.get(this[pool][index]), name: this[pool][index], rot: 180, offset: offset };
        }
      } else {
        return { structure: mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_blank"), name: "hf_mzs/monastery/monastery_tower_blank", rot: 180, offset: offset };
      }
    } else if (pool === `door_pool`) {
      const tag = entity.getTags()[0];

      if (tag === `hf_mzs:origin`) {
        for (let posZ = 1; posZ < 3; posZ++) {
          const newBlock = block.dimension.getBlock(vector.getBlockLocalCoord(block, { x: 0, y: 0, z: -posZ }));
          newBlock.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
        }

        return poolManager.getRandom("door_pool2", 0, block, rotItem, offset, entity);
      } else {
        let newOffset = { x: 0, y: 0, z: -2 };
        let newRot = 0;
        const blockRotation = block.permutation.getState("facing_direction");
        switch (blockRotation) {
          case 2: //North
            newOffset.z += 0;
          case 5: //East
            newRot = 90;
        }
        return poolManager.getRandom("windows_pool", 0, block, rotItem + newRot, newOffset, entity);
      }
    } else if (pool === `tower_door_path_pool`) {
      const structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_door");
      const blockRotation = block.permutation.getState("facing_direction") ?? 4;
      const structureLoc = structurePos(structure, blockRotation, rotItem, 0, offset);
      const dim = block.dimension;
      let start = {
        x: block.location.x + structureLoc.xOff,
        y: block.location.y + structureLoc.yOff,
        z: block.location.z + structureLoc.zOff,
      };
      const rotName = structureManager.toStructureRot.get(structureLoc.rot);
      mc.world.structureManager.place(structure, dim, start, {
        animationMode: mc.StructureAnimationMode.None,
        rotation: rotName,
        includeEntities: true,
      });
    } else if (pool === `stairs_pool`) {
      let structureName = "";
      let newOffset = { x: 0, y: 0, z: 0 };
      let rot = 0;

      const topSolidBlock = block.dimension.getTopmostBlock(vector.getBlockLocalCoord(block, { x: 0, y: -1, z: 1 }), block.location.y);
      const height = topSolidBlock.location.y - block.location.y;

      if (height < -2 && height > -18) {
        const random = Math.random();

        if (random >= 0.9 && height <= -8) {
          const random2 = Math.random();
          if (random2 >= 0.5) {
            const blockFound = block.dimension.getBlock(vector.getBlockLocalCoord(block, { x: 4, y: -5, z: 2 }));
            if (!blockFound || blockFound.typeId === "minecraft:air") {
              structureName = "hf_mzs/monastery/monastery_stairs_left";
              newOffset = newOffsetFunc("left");
            } else {
              structureName = "hf_mzs/monastery/monastery_stairs_down";
              newOffset = newOffsetFunc("down");
            }
          } else {
            const blockFound = block.dimension.getBlock(vector.getBlockLocalCoord(block, { x: -4, y: -5, z: 2 }));
            if (!blockFound || blockFound.typeId === "minecraft:air") {
              structureName = "hf_mzs/monastery/monastery_stairs_right";
              newOffset = newOffsetFunc("right");
              rot = 90;
            } else {
              structureName = "hf_mzs/monastery/monastery_stairs_down";
              newOffset = newOffsetFunc("down");
            }
          }
        } else {
          structureName = "hf_mzs/monastery/monastery_stairs_down";
          newOffset = newOffsetFunc("down");
        }
      } else if (height <= -18) {
        const random = Math.random();

        if (random >= 0.5) {
          structureName = "hf_mzs/monastery/monastery_stairs_end_gong";
          newOffset = newOffsetFunc("gong")
        } else {
          structureName = "hf_mzs/monastery/monastery_stairs_end_spawner";
          newOffset = newOffsetFunc("spawner")
        }
      } else {
        return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
      }

      const structure = mc.world.structureManager.get(structureName);
      const blockRotation = block.permutation.getState("facing_direction");
      const structureLoc = structurePos(structure, blockRotation, rotItem + 180 + rot, 0, vector.add(vector.add(offset, { x: 0, y: -3, z: 2 }), newOffset));
      let start = {
        x: block.location.x + structureLoc.xOff,
        y: block.location.y + structureLoc.yOff,
        z: block.location.z + structureLoc.zOff,
      };
      const rotName = structureManager.toStructureRot.get(structureLoc.rot);

      mc.world.structureManager.place(structure, block.dimension, start, {
        animationMode: mc.StructureAnimationMode.None,
        rotation: rotName,
        includeEntities: true,
      });

      function newOffsetFunc(message) {
        const blockRotation = block.permutation.getState("facing_direction");
        let newOffset2 = { x: 0, y: 0, z: 0 }
        switch (blockRotation) {
          case 5:
            if (message === "down") {
              newOffset2 = { x: -2, y: 0, z: 0 };
            };
            if (message === "gong" || message === "spawner") {
              newOffset2 = { x: -1, y: 0, z: 0 };
            };
            break;
          case 4:
            if (message === "down") {
              newOffset2 = { x: 2, y: 0, z: -4 };
            };
            if (message === "left" || message === "right") {
              newOffset2 = { x: 1, y: 0, z: 0 };
            };
            if (message === "spawner" || message === "gong") {
              newOffset2 = { x: 1, y: 0, z: -1 };
            }
            break;
          case 3:
            if (message === "left" || message === "right") {
              newOffset2 = { x: 1, y: 0, z: 0 }
            };
            break;
        };
        return newOffset2;
      }
    } else if (pool === `entrance_stairs_pool`) {
      let structureName = "";
      let newOffset = { x: 0, y: 0, z: 0 };
      let rot = 0;

      const topSolidBlock = block.dimension.getTopmostBlock(vector.getBlockLocalCoord(block, { x: 0, y: -1, z: 1 }), block.location.y);
      const height = topSolidBlock.location.y - block.location.y;

      if (height < -2) {
        structureName = "hf_mzs/monastery/monastery_stairs_down_full";
        newOffset = newOffsetFunc("down");

        const structure = mc.world.structureManager.get(structureName);
        const blockRotation = block.permutation.getState("facing_direction");
        placeStair({ x: 0, y: -3, z: 2 }, 0)

        function placeStair(newNewOffset, num) {

          if (num < 20) {
            const structureLoc = structurePos(structure, blockRotation, rotItem + 180 + rot, 0, vector.add(vector.add(offset, vector.add(newNewOffset, { x: 0, y: -num, z: num })), newOffset));
            let start = {
              x: block.location.x + structureLoc.xOff,
              y: block.location.y + structureLoc.yOff,
              z: block.location.z + structureLoc.zOff,
            };

            const topSolidBlock = block.dimension.getTopmostBlock(start, (start.y + 1));
            const height = topSolidBlock.location.y - (start.y + 1);

            if (height < 0) {
              const rotName = structureManager.toStructureRot.get(structureLoc.rot);

              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
  
              placeStair(newNewOffset, num + 1)
            } else return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);

          } else if (num < 21) {
            structureName = "hf_mzs/monastery/monastery_stairs_down";
            newOffset = newOffsetFunc("down");

            const structure = mc.world.structureManager.get(structureName);
            const structureLoc = structurePos(structure, blockRotation, rotItem + 180 + rot, 0, vector.add(vector.add(offset, vector.add(newNewOffset, { x: 0, y: -num, z: num })), newOffset));
            let start = {
              x: block.location.x + structureLoc.xOff,
              y: block.location.y + structureLoc.yOff,
              z: block.location.z + structureLoc.zOff,
            };

            const topSolidBlock = block.dimension.getTopmostBlock(start, (start.y + 1));
            const height = topSolidBlock.location.y - (start.y + 1);

            if (height < 0) {
              const rotName = structureManager.toStructureRot.get(structureLoc.rot);

              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
  
              placeStair(newNewOffset, num + 1)
            }  
          }
        }

      } else return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);

      function newOffsetFunc(message) {
        const blockRotation = block.permutation.getState("facing_direction");
        let newOffset2 = { x: 0, y: 0, z: 0 }
        switch (blockRotation) {
          case 5:
            if (message === "down") {
              newOffset2 = { x: -2, y: 0, z: 0 };
            };
            if (message === "gong" || message === "spawner") {
              newOffset2 = { x: -1, y: 0, z: 0 };
            };
            break;
          case 4:
            if (message === "down") {
              newOffset2 = { x: 2, y: 0, z: -4 };
            };
            if (message === "left" || message === "right") {
              newOffset2 = { x: 1, y: 0, z: 0 };
            };
            if (message === "spawner" || message === "gong") {
              newOffset2 = { x: 1, y: 0, z: -1 };
            }
            break;
          case 3:
            if (message === "left" || message === "right") {
              newOffset2 = { x: 1, y: 0, z: 0 }
            };
            break;
        };
        return newOffset2;
      }
    } else if (pool === `room_pool` || pool === `room_no_decor_pool`) {
      let type = "";
      const randomType = Math.random();
      if (randomType > 0.6) {
        type = "hf_mzs:library";
      } else if (randomType > 0.3 && randomType <= 0.6) {
        type = "hf_mzs:storage";
      } else if (randomType <= 0.3) {
        type = "hf_mzs:dojo";
      }

      const topSolidBlock = block.dimension.getTopmostBlock(vector.getBlockLocalCoord(block, vector.add(offset, { x: 0, y: 0, z: 3 })), block.dimension.heightRange.max);
      const height = topSolidBlock.location.y - block.location.y;
      //mc.world.sendMessage(`${height} ${topSolidBlock.typeId} ${JSON.stringify(vector.getBlockLocalCoord(block, {x: 0, y: 0, z: 1}))}`)

      if (height >= -7) {
        let structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_base");
        if (pool === `room_no_decor_pool`) {
          structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_base_no_decor");
        }
        const blockRotation = block.permutation.getState("facing_direction");
        const structureLoc = structurePos(structure, blockRotation, rotItem, 0, offset);
        let start = {
          x: block.location.x + structureLoc.xOff,
          y: block.location.y + structureLoc.yOff,
          z: block.location.z + structureLoc.zOff,
        };
        const rotName = structureManager.toStructureRot.get(structureLoc.rot);

        mc.world.structureManager.place(structure, block.dimension, start, {
          animationMode: mc.StructureAnimationMode.None,
          rotation: rotName,
          includeEntities: true,
        });
        block.dimension.runCommand(
          `/tag @e[type=hf_mzs:custom_jigsaw_util,tag=!hf_mzs:origin,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:origin`
        );
        block.dimension.runCommand(
          `/tag @e[type=hf_mzs:custom_jigsaw_util,tag=!hf_mzs:origin,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:base`
        );
        mc.system.run(() => {
          block.dimension.runCommand(
            `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
          );
          block.dimension.runCommand(
            `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:base`
          );
          start.y += 5;
          putTop();
          function putTop() {
            start.y += 6;
            const topSolidBlock = block.dimension.getTopmostBlock(start, block.dimension.heightRange.max);
            const height = topSolidBlock.location.y - start.y;
            if (height >= 3) {
              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_middle");
              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
              );

              putTop();
            } else {
              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_top");
              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
              );

              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_roof");
              start.y += 4;

              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
            }
          }
        });
      } else {
        let structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_top");
        const blockRotation = block.permutation.getState("facing_direction");
        let structureLoc = structurePos(structure, blockRotation, rotItem, 0, { x: 3, y: 1, z: -3 });
        let start = {
          x: block.location.x + structureLoc.xOff,
          y: block.location.y + structureLoc.yOff + 5,
          z: block.location.z + structureLoc.zOff,
        };
        const rotName = structureManager.toStructureRot.get(structureLoc.rot);

        mc.world.structureManager.place(structure, block.dimension, start, {
          animationMode: mc.StructureAnimationMode.None,
          rotation: rotName,
          includeEntities: true,
        });
        block.dimension.runCommand(
          `/tag @e[type=hf_mzs:custom_jigsaw_util,tag=!hf_mzs:origin,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:origin`
        );
        structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_roof");
        start.y += 4;
        mc.world.structureManager.place(structure, block.dimension, start, {
          animationMode: mc.StructureAnimationMode.None,
          rotation: rotName,
          includeEntities: true,
        });
        mc.system.run(() => {
          block.dimension.runCommand(
            `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
          );
          start.y -= 4;
          putBase();
          function putBase() {
            start.y -= 6;
            const topSolidBlock = block.dimension.getTopmostBlock(start, start.y);
            const height = topSolidBlock.location.y - start.y;
            if (height <= -10) {
              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_middle");
              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
              );
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:base`
              );

              putBase();
            } else {
              structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_base");
              if (pool === `room_no_decor_pool`) {
                structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_room_base_no_decor");
              }
              mc.world.structureManager.place(structure, block.dimension, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
              });
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add ${type}`
              );
              block.dimension.runCommand(
                `/tag @e[type=hf_mzs:custom_jigsaw_util,x=${start.x},y=${start.y},z=${start.z},dx=${structure.size.x},dy=${structure.size.y},dz=${structure.size.z}] add hf_mzs:base`
              );
            }
          }
        });
      }
    } else if (pool === `room_path_pool` || pool === `room_path_pool2`) {
      const tag = entity.getTags()[0];
      const blockList = structureBlockList();
      const maxDistance = 10;

      for (let offsetZ = 4; offsetZ <= maxDistance; offsetZ++) {
        const checkPosition = vector.getBlockLocalCoord(block, { x: 0, y: 0, z: offsetZ });
        const topSolidBlock = block.dimension.getTopmostBlock(checkPosition, block.dimension.heightRange.max);
        const height = topSolidBlock.location.y - block.location.y;

        if (blockList.includes(topSolidBlock.typeId) || tag === `hf_mzs:origin` || Math.abs(height) >= 20) {
          //mc.world.sendMessage(`room: ${topSolidBlock.typeId} ${height} ${tag} ${JSON.stringify(topSolidBlock.location)}`)
          if (pool === `room_path_pool2` && tag === `hf_mzs:origin`) {
            const structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_blank");
            const blockRotation = block.permutation.getState("facing_direction");
            const structureLoc = structurePos(structure, blockRotation, rotItem, 0, { x: -3, y: 0, z: -1 });
            let start = {
              x: block.location.x + structureLoc.xOff,
              y: block.location.y + structureLoc.yOff,
              z: block.location.z + structureLoc.zOff,
            };
            const rotName = structureManager.toStructureRot.get(structureLoc.rot);

            mc.world.structureManager.place(structure, block.dimension, start, {
              animationMode: mc.StructureAnimationMode.None,
              rotation: rotName,
              includeEntities: true,
            });
            let posToBreak = [];
            for (let posY = 0; posY <= 3; posY++) {
              for (let posZ = -3; posZ <= 3; posZ++) {
                const pos = vector.getBlockLocalCoord(block, { x: -3, y: posY, z: posZ });
                posToBreak.push(pos);
              }
            }
            mc.system.runTimeout(() => {
              posToBreak.forEach((pos) => {
                const newBlock = block.dimension.getBlock(pos);
                newBlock.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
              });
            }, 10);
            return { structure: mc.world.structureManager.get(`hf_mzs/void`), name: "hf_mzs/void", rot: 0, offset: { x: 0, y: 0, z: 0 } };
          } else {
            return poolManager.getRandom("room_windows_pool", 0, block, rotItem, offset, entity);
          }
        }
      }

      const random = Math.random();
      if (random >= 0.6) {
        const random2 = Math.random();
        if (random2 >= 0.5) {
          const structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_blank");
          const blockRotation = block.permutation.getState("facing_direction");
          const structureLoc = structurePos(structure, blockRotation, rotItem, 0, { x: -3, y: 0, z: -1 });
          let start = {
            x: block.location.x + structureLoc.xOff,
            y: block.location.y + structureLoc.yOff,
            z: block.location.z + structureLoc.zOff,
          };
          const rotName = structureManager.toStructureRot.get(structureLoc.rot);

          mc.world.structureManager.place(structure, block.dimension, start, {
            animationMode: mc.StructureAnimationMode.None,
            rotation: rotName,
            includeEntities: true,
          });
          return poolManager.getRandom("center_walls_pool", 90, block, rotItem, vector.add(offset, { x: 3, y: -5, z: 1 }), entity);
        } else {
          mc.system.runTimeout(() => {
            const structure = mc.world.structureManager.get("hf_mzs/monastery/monastery_tower_blank");
            const blockRotation = block.permutation.getState("facing_direction");
            const structureLoc = structurePos(structure, blockRotation, rotItem, 0, { x: 3, y: 0, z: -1 });
            let start = {
              x: block.location.x + structureLoc.xOff,
              y: block.location.y + structureLoc.yOff,
              z: block.location.z + structureLoc.zOff,
            };
            const rotName = structureManager.toStructureRot.get(structureLoc.rot);

            mc.world.structureManager.place(structure, block.dimension, start, {
              animationMode: mc.StructureAnimationMode.None,
              rotation: rotName,
              includeEntities: true,
            });
            return poolManager.getRandom("room_no_decor_pool", 0, block, rotItem, { x: 0, y: -5, z: -2 }, entity);
          }, 5);
        }
      } else {
        const random2 = Math.random();
        if (random2 >= 0.6) {
          return poolManager.getRandom("room_expansion_pool", 180, block, rotItem, { x: 0, y: -3, z: -3 }, entity);
        } else {
          return poolManager.getRandom("room_windows_pool", 0, block, rotItem, offset, entity);
        }
      }
    } else if (pool === `room_windows_pool`) {
      function balconyOffset(initialCoord, name) {
        if (name === "hf_mzs/monastery/monastery_balcony") {
          const blockRotation = block.permutation.getState("facing_direction");
          let balconyOffsetVal = vector.add(initialCoord, { x: 0, y: -2, z: 2 });

          if (blockRotation === 4) {
            balconyOffsetVal = vector.add(initialCoord, { x: 0, y: -2, z: 0 });
          } else if (blockRotation === 5 && initialCoord.x > 0) {
            balconyOffsetVal = vector.add(initialCoord, { x: -1, y: -2, z: 2 });
          };

          return balconyOffsetVal;
        } else return initialCoord;
      };
      function roomDoorOffset(initialCoord, name) {
        if (name === "hf_mzs/monastery/monastery_room_door") {
          const blockRotation = block.permutation.getState("facing_direction");
          let doorOffset = vector.add(initialCoord, { x: 0, y: -3, z: 5 });
          if (blockRotation === 4) {
            doorOffset = vector.add(initialCoord, { x: 4, y: -3, z: -3 });
          } else if (blockRotation === 5) {
            doorOffset = vector.add(initialCoord, { x: -4, y: -3, z: 5 });
          }
          return doorOffset;
        } else return initialCoord;
      }

      const blockFront = block.dimension.getBlock(vector.getBlockLocalCoord(block, { x: 0, y: 1, z: 1 }));
      const random = Math.random();
      if (random >= 0.6 && (!blockFront || blockFront.typeId === `minecraft:air`)) {
        let structureName = "";
        let newRot = 0;

        if (entity?.hasTag("hf_mzs:base")) {
          const random2 = Math.random();
          const blockFound2 = block.dimension.getBlock(vector.getBlockLocalCoord(block, { x: 0, y: -4, z: 6 }));
          if (random2 >= 0.6 && (!blockFound2 || blockFound2.typeId === `minecraft:air`)) {
            structureName = "hf_mzs/monastery/monastery_room_door";
            newRot = 180;
          } else {
            structureName = "hf_mzs/monastery/monastery_tower_window1_center";
          }
        } else {
          structureName = "hf_mzs/monastery/monastery_tower_window1_center";
        }

        const structure = mc.world.structureManager.get(structureName);
        const blockRotation = block.permutation.getState("facing_direction") ?? 4;
        const structureLoc = structurePos(structure, blockRotation, rotItem + newRot, 0, roomDoorOffset({ x: 0, y: 0, z: -4 }, structureName));
        const dim = block.dimension;
        let start = {
          x: block.location.x + structureLoc.xOff,
          y: block.location.y + structureLoc.yOff,
          z: block.location.z + structureLoc.zOff,
        };
        const rotName = structureManager.toStructureRot.get(structureLoc.rot);

        mc.system.runTimeout(() => {
          mc.world.structureManager.place(structure, dim, start, {
            animationMode: mc.StructureAnimationMode.None,
            rotation: rotName,
            includeEntities: true,
          });
          if (structureName === "hf_mzs/monastery/monastery_room_door") {
            dim.runCommand(`fill ${block.location.x - 1} ${block.location.y} ${block.location.z - 1} ${block.location.x + 1} ${block.location.y + 2} ${block.location.z + 1} minecraft:air`);
          }
        }, 40)
      } else {
        let structureName = "";
        const random2 = Math.random();
        const random4 = Math.random();
        if (random2 >= 0.5 && (!blockFront || blockFront.typeId === `minecraft:air`)) {
          if (!entity?.hasTag("hf_mzs:base") && !entity?.hasTag("hf_mzs:room_expansion") && random4 >= 0.8) {
            structureName = "hf_mzs/monastery/monastery_balcony";
          } else {
            structureName = "hf_mzs/monastery/monastery_tower_window1";
          }
        } else {
          structureName = "hf_mzs/monastery/monastery_tower_blank";
        }

        const structure = mc.world.structureManager.get(structureName);
        const blockRotation = block.permutation.getState("facing_direction");
        const structureLoc = structurePos(structure, blockRotation, rotItem + 180, 0, balconyOffset({ x: 3, y: 0, z: -1 }, structureName));
        let start = {
          x: block.location.x + structureLoc.xOff,
          y: block.location.y + structureLoc.yOff,
          z: block.location.z + structureLoc.zOff,
        };
        const rotName = structureManager.toStructureRot.get(structureLoc.rot);
        const dim = block.dimension;

        mc.system.runTimeout(() => {
          mc.world.structureManager.place(structure, dim, start, {
            animationMode: mc.StructureAnimationMode.None,
            rotation: rotName,
            includeEntities: true,
          });
        }, 40)

        const random3 = Math.random();
        const random5 = Math.random();
        if (random3 >= 0.5 && (!blockFront || blockFront.typeId === `minecraft:air`)) {
          if (!entity?.hasTag("hf_mzs:base") && !entity?.hasTag("hf_mzs:room_expansion") && random5 >= 0.8) {
            structureName = "hf_mzs/monastery/monastery_balcony";
          } else {
            structureName = "hf_mzs/monastery/monastery_tower_window1";
          }
        } else {
          structureName = "hf_mzs/monastery/monastery_tower_blank";
        }
        const structure2 = mc.world.structureManager.get(structureName);
        const structureLoc2 = structurePos(structure, blockRotation, rotItem + 180, 0, balconyOffset({ x: -3, y: 0, z: -1 }, structureName));
        let start2 = {
          x: block.location.x + structureLoc2.xOff,
          y: block.location.y + structureLoc2.yOff,
          z: block.location.z + structureLoc2.zOff,
        };
        const rotName2 = structureManager.toStructureRot.get(structureLoc2.rot);

        mc.system.runTimeout(() => {
          mc.world.structureManager.place(structure2, dim, start2, {
            animationMode: mc.StructureAnimationMode.None,
            rotation: rotName2,
            includeEntities: true,
          });
        }, 40)
      }
      try {
        const inv = block.getComponent("inventory");
        inv?.container?.clearAll();
      } catch { }
      block.setPermutation(mc.BlockPermutation.resolve("minecraft:white_concrete"));
    } else if (pool === `deepslate_base_pool`) {
      const deepslateList = ["minecraft:cobbled_deepslate", "minecraft:polished_deepslate"];
      placeDeepslate(block.location, block.dimension);
      function placeDeepslate(blockLocation, dimension) {
        const index = selectors.getRandomQuantity(0, 1);
        let location = blockLocation;
        location.y -= 1;
        const newBlock = dimension.getBlock(location);
        const topSolidBlock = block.dimension.getTopmostBlock(location, location.y);
        const height = topSolidBlock.location.y - location.y;
        if (height < 0) {
          const inventory = block.getComponent("inventory");
          try {
            inventory.container.clearAll();
          } catch { }
          newBlock.setPermutation(mc.BlockPermutation.resolve(deepslateList[index]));
          placeDeepslate(location, dimension);
        } else {
          const items = dimension.getEntities({ location: blockLocation, maxDistance: 50, type: `minecraft:item` });
          items.forEach((item) => {
            const itemStack = item.getComponent("item").itemStack;
            if (itemStack.typeId === `minecraft:cobbled_deepslate` || itemStack.typeId === `minecraft:paper`) {
              if (item?.isValid() === true) {
                item?.remove();
              }
            }
          });
        }
      }
    } else if (pool === `bluff_spawn`) {
      return;
    } else if (pool === `interior_wall_pool`) {
      const tags = entity.getTags();
      let tag = "";
      if (tags && tags.length > 0) {
        tags.forEach((e) => {
          if (e === `hf_mzs:library` || e === `hf_mzs:storage` || e === `hf_mzs:dojo`) {
            tag = e;
          }
        });
      } else {
        //mc.world.sendMessage(`noTags`)
        return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
      }
      //mc.world.sendMessage(`${tag}`)

      const elements = [
        { weight: 10, element: "void_pool", offset: { x: 0, y: 0, z: 0 }, size: { x: 0, y: 0, z: 0 } },
        { weight: 1, element: "banners_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
      ];
      switch (tag) {
        case "hf_mzs:library":
          elements.push(
            { weight: 4, element: "bookshelf_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 4, z: 0 } },
            { weight: 4, element: "bookshelf_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 4, element: "bookshelf_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 2, z: 0 }, type: true },
            { weight: 4, element: "bookshelf_pool4", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 3, z: 0 } },
            { weight: 4, element: "desk_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 4, element: "desk_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 4, element: "desk_pool3", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 4, element: "desk_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 0, z: 0 }, type: true },
            { weight: 4, element: "gong_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 2, y: 1, z: 1 } },
            { weight: 1, element: "spawner_pool", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 2, z: 1 } }
          );
          break;
        case "hf_mzs:storage":
          elements.push(
            { weight: 4, element: "barrels_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 4, element: "barrels_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 4, element: "barrels_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 4, element: "barrels_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 4, element: "shelf_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 0 } },
            { weight: 1, element: "spawner_pool", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 2, z: 1 } }
          );
          break;
        case "hf_mzs:dojo":
          elements.push(
            { weight: 4, element: "dummies_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 4, element: "dummies_pool2", offset: { x: 0, y: 1, z: -1 }, size: { x: 0, y: 1, z: 0 } },
            { weight: 4, element: "weapons_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 4, element: "gong_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 4, element: "punching_bag_wall_pool", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 5, z: 0 } },
            { weight: 4, element: "training_post_wall_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 1 } },
            { weight: 1, element: "spawner_pool", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 2, z: 1 } }
          );
          break;
      }

      const totalWeight = elements.reduce((sum, item) => sum + item.weight, 0);
      const random = Math.random() * totalWeight;

      let accumulatedWeight = 0;
      let selectedElement = "void_pool";
      let newOffset = { x: 0, y: 0, z: 0 };

      for (const item of elements) {
        accumulatedWeight += item.weight;
        if (random < accumulatedWeight) {
          selectedElement = item.element;
          newOffset = item.offset;

          if (item?.type === true) {
            const blockRotation = block.permutation.getState("facing_direction");
            switch (blockRotation) {
              case 4: //West
                newOffset.x += 1;
                newOffset.z -= 1;
                break;
              case 2: //North
                newOffset.x += 1;
                break;
            }
          };
          if (item.element === `spawner_pool`) {
            const blockRotation = block.permutation.getState("facing_direction");

            if (blockRotation === 5) {
              newOffset.x -= 1;
            } else if (blockRotation === 4) {
              newOffset.z -= 2;
              newOffset.x += 1;
            }
          }

          const blockVol = block?.dimension.getBlocks(selectors.getVolumeFromLocalCoords(block, { x: -item.size.x, y: 1, z: -item.size.z }, item.size), { excludeTypes: ["minecraft:air", "minecraft:white_concrete", "minecraft:calcite", "minecraft:diorite", "hf_mzs:white_concrete_dummy", "minecraft:polished_deepslate", "minecraft:cobbled_deepslate", "minecraft:red_terracotta", "minecraft:stripped_dark_oak_log", "minecraft:birch_fence", "minecraft:dark_oak_double_slab"] }, true);

          for (const blockLocs of blockVol.getBlockLocationIterator()) {
            const newBlock = block.dimension.getBlock(blockLocs);
            if (newBlock) {

              return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
            }
          }
          break;
        }
      }

      return poolManager.getRandom(selectedElement, 0, block, rotItem, newOffset, entity);
    } else if (pool === `interior_wall_small_pool`) {
      const tags = entity.getTags();
      let tag = "";
      if (tags && tags.length > 0) {
        tags.forEach((e) => {
          if (e === `hf_mzs:library` || e === `hf_mzs:storage` || e === `hf_mzs:dojo`) {
            tag = e;
          }
        });
      } else {
        //mc.world.sendMessage(`noTags`)
        return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
      }
      //mc.world.sendMessage(`${tag}`)

      const elements = [
        { weight: 10, element: "void_pool", offset: { x: 0, y: 0, z: 0 }, size: { x: 1, y: 1, z: 1 } },
        { weight: 1, element: "banners_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
      ];
      switch (tag) {
        case "hf_mzs:library":
          elements.push(
            { weight: 1, element: "bookshelf_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "bookshelf_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 2, z: 0 }, type: true },
            { weight: 1, element: "desk_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 1, element: "desk_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "desk_pool3", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 1, element: "desk_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 0, z: 0 }, type: true },
            { weight: 1, element: "gong_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 3, y: 3, z: 3 } }
          );
          break;
        case "hf_mzs:storage":
          elements.push(
            { weight: 1, element: "barrels_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 1, element: "barrels_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "barrels_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 1, element: "barrels_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 1, element: "shelf_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 0 } }
          );
          break;
        case "hf_mzs:dojo":
          elements.push(
            { weight: 1, element: "dummies_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 1, element: "dummies_pool2", offset: { x: 0, y: 1, z: -1 }, size: { x: 0, y: 1, z: 0 } },
            { weight: 1, element: "weapons_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 1, element: "training_post_wall_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 1 } }
          );
          break;
      }

      const totalWeight = elements.reduce((sum, item) => sum + item.weight, 0);
      const random = Math.random() * totalWeight;

      let accumulatedWeight = 0;
      let selectedElement = "void_pool";
      let newOffset = { x: 0, y: 0, z: 0 };

      for (const item of elements) {
        accumulatedWeight += item.weight;
        if (random < accumulatedWeight) {
          selectedElement = item.element;
          newOffset = item.offset;

          if (item?.type === true) {
            const blockRotation = block.permutation.getState("facing_direction");
            switch (blockRotation) {
              case 4: //West
                newOffset.x += 1;
                newOffset.z -= 1;
                break;
              case 2: //North
                newOffset.x += 1;
                break;
            }
          };

          const blockVol = block.dimension.getBlocks(selectors.getVolumeFromLocalCoords(block, { x: -item.size.x, y: 1, z: -item.size.z }, item.size), { excludeTypes: ["minecraft:air", "minecraft:white_concrete", "minecraft:calcite", "minecraft:diorite", "hf_mzs:white_concrete_dummy", "minecraft:polished_deepslate", "minecraft:cobbled_deepslate", "minecraft:red_terracotta", "minecraft:stripped_dark_oak_log", "minecraft:birch_fence", "minecraft:dark_oak_double_slab"] }, true);

          for (const blockLocs of blockVol.getBlockLocationIterator()) {
            const newBlock = block.dimension.getBlock(blockLocs);
            if (newBlock) {

              return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
            }
          }
          break;
        }
      }

      return poolManager.getRandom(selectedElement, 0, block, rotItem, newOffset, entity);
    } else if (pool === `interior_wall_corner_pool`) {
      const tags = entity.getTags();
      let tag = "";
      if (tags && tags.length > 0) {
        tags.forEach((e) => {
          if (e === `hf_mzs:library` || e === `hf_mzs:storage` || e === `hf_mzs:dojo`) {
            tag = e;
          }
        });
      } else {
        //mc.world.sendMessage(`noTags`)
        return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
      }
      //mc.world.sendMessage(`${tag}`)

      const elements = [
        { weight: 10, element: "void_pool", offset: { x: 0, y: 0, z: 0 }, size: { x: 0, y: 0, z: 0 } },
        { weight: 1, element: "banners_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
        { weight: 1, element: "gong_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 2, y: 1, z: 1 } },
      ];
      switch (tag) {
        case "hf_mzs:library":
          elements.push(
            { weight: 1, element: "bookshelf_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 4, z: 0 } },
            { weight: 1, element: "bookshelf_pool2", offset: { x: -1, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "bookshelf_pool3", offset: { x: -1, y: 1, z: 0 }, size: { x: 1, y: 2, z: 0 }, type: true },
            { weight: 1, element: "bookshelf_pool4", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 3, z: 0 } },
            { weight: 1, element: "desk_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 1, element: "desk_pool2", offset: { x: -1, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "desk_pool3", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 1, element: "desk_pool4", offset: { x: -1, y: 1, z: 0 }, size: { x: 1, y: 0, z: 0 }, type: true },
            { weight: 1, element: "gong_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 2, y: 1, z: 1 } }
          );
          break;
        case "hf_mzs:storage":
          elements.push(
            { weight: 1, element: "barrels_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 1, element: "barrels_pool2", offset: { x: -1, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "barrels_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 1, element: "barrels_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 1, element: "shelf_pool", offset: { x: -2, y: 1, z: -2 }, size: { x: 2, y: 4, z: 0 } }
          );
          break;
        case "hf_mzs:dojo":
          elements.push(
            { weight: 1, element: "dummies_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 1, element: "dummies_pool2", offset: { x: -1, y: 1, z: -1 }, size: { x: 0, y: 1, z: 0 } },
            { weight: 1, element: "weapons_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 1, element: "gong_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 1, element: "punching_bag_wall_pool", offset: { x: -1, y: 1, z: 0 }, size: { x: 0, y: 5, z: 0 } },
            { weight: 1, element: "training_post_wall_pool", offset: { x: -1, y: 1, z: -1 }, size: { x: 1, y: 2, z: 1 } },
            { weight: 1, element: "shrine_pool", offset: { x: -2, y: 1, z: -2 }, size: { x: 2, y: 4, z: 0 } }
          );
          break;
      }

      const totalWeight = elements.reduce((sum, item) => sum + item.weight, 0);
      const random = Math.random() * totalWeight;

      let accumulatedWeight = 0;
      let selectedElement = "void_pool";
      let newOffset = { x: 0, y: 0, z: 0 };

      for (const item of elements) {
        accumulatedWeight += item.weight;
        if (random < accumulatedWeight) {
          selectedElement = item.element;
          newOffset = item.offset;

          if (item?.type === true) {
            const blockRotation = block.permutation.getState("facing_direction");
            switch (blockRotation) {
              case 4: //West
                newOffset.x += 1;
                newOffset.z -= 1;
                break;
              case 2: //North
                newOffset.x += 1;
                break;
            }
          };

          const blockVol = block.dimension.getBlocks(selectors.getVolumeFromLocalCoords(block, vector.add({ x: -item.size.x, y: 1, z: -item.size.z }, item.offset), vector.add(item.size, item.offset)), { excludeTypes: ["minecraft:air", "minecraft:white_concrete", "minecraft:calcite", "minecraft:diorite", "hf_mzs:white_concrete_dummy", "minecraft:polished_deepslate", "minecraft:cobbled_deepslate", "minecraft:red_terracotta", "minecraft:stripped_dark_oak_log", "minecraft:birch_fence", "minecraft:dark_oak_double_slab"] }, true);

          for (const blockLocs of blockVol.getBlockLocationIterator()) {
            const newBlock = block.dimension.getBlock(blockLocs);
            if (newBlock) {

              return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
            }
          }
          break;
        }
      }

      return poolManager.getRandom(selectedElement, 0, block, rotItem, newOffset, entity);
    } else if (pool === `interior_center_pool` || pool === `interior_center_base_pool`) {
      const tags = entity.getTags();
      let tag = "";
      if (tags && tags.length > 0) {
        tags.forEach((e) => {
          if (e === `hf_mzs:library` || e === `hf_mzs:storage` || e === `hf_mzs:dojo`) {
            tag = e;
          }
        });
      } else {
        //mc.world.sendMessage(`noTags`)
        return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
      }
      //mc.world.sendMessage(`${tag}`)

      let elements;
      if (pool === `interior_center_pool`) {
        elements = [
          { weight: 5, element: "void_pool", offset: { x: 0, y: 0, z: 0 }, size: { x: 1, y: 1, z: 1 } },
          { weight: 3, element: "landing_pool", offset: { x: 0, y: 0, z: -2 }, size: { x: 5, y: 6, z: 5 } },
          { weight: 1, element: "partition_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 9, y: 5, z: 9 } },
        ];
      } else if (pool === `interior_center_base_pool`) {
        elements = [
          { weight: 1, element: "void_pool", offset: { x: 0, y: 0, z: 0 }, size: { x: 1, y: 1, z: 1 } },
          { weight: 1, element: "partition_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 9, y: 5, z: 9 } },
        ];
      }
      switch (tag) {
        case "hf_mzs:library":
          elements.push(
            { weight: 1, element: "bookshelf_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 4, z: 0 } },
            { weight: 1, element: "bookshelf_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "bookshelf_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 2, z: 0 }, type: true },
            { weight: 1, element: "bookshelf_pool4", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 3, z: 0 } },
            { weight: 1, element: "desk_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 1, element: "desk_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "desk_pool3", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 1, element: "desk_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 0, z: 0 }, type: true },
            { weight: 1, element: "gong_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 1, element: "statue_center_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 2 } }
          );
          break;
        case "hf_mzs:storage":
          elements.push(
            { weight: 1, element: "barrels_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 1, element: "barrels_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "barrels_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 1, element: "barrels_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 1, element: "shelf_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 0 } }
          );
          break;
        case "hf_mzs:dojo":
          elements.push(
            { weight: 1, element: "dummies_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 1, element: "dummies_pool2", offset: { x: 0, y: 1, z: -1 }, size: { x: 0, y: 1, z: 0 } },
            { weight: 1, element: "weapons_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 1, element: "gong_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 1, element: "punching_bag_wall_pool", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 5, z: 0 } },
            { weight: 1, element: "training_post_wall_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 1 } },
            { weight: 1, element: "shrine_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 0 } },
            { weight: 1, element: "statue_center_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 2 } },
            { weight: 2, element: "dojo_pool", offset: { x: 0, y: 1, z: -3 }, size: { x: 2, y: 5, z: 2 } }
          );
          break;
      }

      const totalWeight = elements.reduce((sum, item) => sum + item.weight, 0);
      const random = Math.random() * totalWeight;

      let accumulatedWeight = 0;
      let selectedElement = "void_pool";
      let newOffset = { x: 0, y: 0, z: 0 };

      for (const item of elements) {
        accumulatedWeight += item.weight;
        if (random < accumulatedWeight) {
          selectedElement = item.element;
          newOffset = item.offset;

          if (item?.type === true) {
            const blockRotation = block.permutation.getState("facing_direction");
            switch (blockRotation) {
              case 4: //West
                newOffset.x += 1;
                newOffset.z -= 1;
                break;
              case 2: //North
                newOffset.x += 1;
                break;
            }
          }
          break;
        }
      }

      return poolManager.getRandom(selectedElement, 0, block, rotItem, newOffset, entity);
    } else if (pool === `interior_wall_middle_pool`) {
      const tags = entity.getTags();
      let tag = "";
      if (tags && tags.length > 0) {
        tags.forEach((e) => {
          if (e === `hf_mzs:library` || e === `hf_mzs:storage` || e === `hf_mzs:dojo`) {
            tag = e;
          }
        });
      } else {
        //mc.world.sendMessage(`noTags`)
        return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
      }
      //mc.world.sendMessage(`${tag}`)

      const elements = [
        { weight: 10, element: "void_pool", offset: { x: 0, y: 0, z: 0 }, size: { x: 1, y: 1, z: 1 } },
        { weight: 1, element: "banners_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
      ];
      switch (tag) {
        case "hf_mzs:library":
          elements.push(
            { weight: 1, element: "bookshelf_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 4, z: 0 } },
            { weight: 1, element: "bookshelf_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "bookshelf_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 2, z: 0 }, type: true },
            { weight: 1, element: "bookshelf_pool4", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 3, z: 0 } },
            { weight: 1, element: "desk_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 1, element: "desk_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "desk_pool3", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 1, element: "desk_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 0, z: 0 }, type: true },
            { weight: 1, element: "gong_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 1, element: "statue_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 3 } }
          );
          break;
        case "hf_mzs:storage":
          elements.push(
            { weight: 1, element: "barrels_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 1 } },
            { weight: 1, element: "barrels_pool2", offset: { x: 0, y: 1, z: 0 }, size: { x: 1, y: 1, z: 0 }, type: true },
            { weight: 1, element: "barrels_pool3", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 1, element: "barrels_pool4", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 0, z: 0 } },
            { weight: 1, element: "shelf_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 0 } }
          );
          break;
        case "hf_mzs:dojo":
          elements.push(
            { weight: 1, element: "dummies_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 1, z: 0 } },
            { weight: 1, element: "dummies_pool2", offset: { x: 0, y: 1, z: -1 }, size: { x: 0, y: 1, z: 0 } },
            { weight: 1, element: "weapons_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 1, element: "gong_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 0 } },
            { weight: 2, element: "punching_bag_wall_pool", offset: { x: 0, y: 1, z: 0 }, size: { x: 0, y: 5, z: 0 } },
            { weight: 2, element: "training_post_wall_pool", offset: { x: 0, y: 1, z: -1 }, size: { x: 1, y: 2, z: 1 } },
            { weight: 1, element: "statue_pool", offset: { x: 0, y: 1, z: -2 }, size: { x: 2, y: 4, z: 3 } }
          );
          break;
      }

      const totalWeight = elements.reduce((sum, item) => sum + item.weight, 0);
      const random = Math.random() * totalWeight;

      let accumulatedWeight = 0;
      let selectedElement = "void_pool";
      let newOffset = { x: 0, y: 0, z: 0 };

      for (const item of elements) {
        accumulatedWeight += item.weight;
        if (random < accumulatedWeight) {
          selectedElement = item.element;
          newOffset = item.offset;

          if (item?.type === true) {
            const blockRotation = block.permutation.getState("facing_direction");
            switch (blockRotation) {
              case 4: //West
                newOffset.x += 1;
                newOffset.z -= 1;
                break;
              case 2: //North
                newOffset.x += 1;
                break;
            }
          }
          break;
        }
      }

      return poolManager.getRandom(selectedElement, 0, block, rotItem, newOffset, entity);
    } else if (pool === `room_expansion_pool`) {
      const tags = entity.getTags();
      let tag = "";
      if (tags && tags.length > 0) {
        tags.forEach((e) => {
          if (e === `hf_mzs:library` || e === `hf_mzs:storage` || e === `hf_mzs:dojo`) {
            tag = e;
          }
        });
      } else {
        return poolManager.getRandom("void_pool", 0, block, rotItem, offset, entity);
      }
      block.dimension.runCommand(`/tag @e[r=5] add ${tag}`);
      block.dimension.runCommand(`/tag @e[r=5] add hf_mzs:room_expansion`);
      return { structure: mc.world.structureManager.get(this[pool][index]), name: this[pool][index], rot: Number(newRot), offset: offset };
    } else {
      return { structure: mc.world.structureManager.get(this[pool][index]), name: this[pool][index], rot: Number(newRot), offset: offset };
    }
  },
  getAtIndex(pool, index) {
    return mc.world.structureManager.get(this[pool][index]);
  },
  getFirst(pool) {
    return mc.world.structureManager.get(this[pool][0]);
  },
  getLast(pool) {
    return mc.world.structureManager.get(this[pool][this[pool].length]);
  },
  randomize(pool, rot, block, rotItem, Offset, entity) {
    const offset = { x: 0, y: 0, z: 0 };
    const random = Math.random();
    if (random < 0.1) {
      if (pool === `room_expansion_pool`) {
        return poolManager.getRandom(pool, rot, block, rotItem, offset, entity);
      } else {
        return poolManager.getRandom(pool, rot, block, rotItem, offset, entity);
      }
    } else {
      return { structure: mc.world.structureManager.get(`hf_mzs/void`), name: "hf_mzs/void", rot: 0, offset: { x: 0, y: 0, z: 0 } };
    }
  },

  //Pieces, Exterior
  void_pool: ["hf_mzs/void"],
  extend_deepslate: ["hf_mzs/monastery_deepslate"],
  test_pool: ["hf_mzs/monastery/monastery_center_back_3way", "hf_mzs/monastery/monastery_center_back", "hf_mzs/monastery/monastery_center_doorway"],
  test_zone_pool: ["hf_mzs/monastery/monastery_test_zone"],
  center_door_pool: ["hf_mzs/monastery/monastery_center_doorway"],
  center_walls_pool: ["hf_mzs/monastery/monastery_wall_straight_center"],
  wall_gap_pool: ["hf_mzs/monastery/monastery_wall_straight", "hf_mzs/monastery/monastery_wall_gap"],
  wall_pool: ["a"],
  center_back_pool: ["hf_mzs/monastery/monastery_center_back", "hf_mzs/monastery/monastery_center_back_3way"],
  center_corners_pool: ["hf_mzs/monastery/monastery_wall_corner", "hf_mzs/monastery/monastery_wall_3way", "hf_mzs/monastery/monastery_wall_4way"],
  accent_pool: ["hf_mzs/monastery/monastery_wall_accent"],
  crown_pool: ["hf_mzs/monastery/monastery_crown"],
  connector_pool: [
    "hf_mzs/monastery/monastery_wall_connector",
    "hf_mzs/monastery/monastery_wall_connector",
    "hf_mzs/monastery/monastery_wall_connector",
    "hf_mzs/monastery/monastery_wall_connector_end",
  ],
  connector_exit: ["hf_mzs/monastery/monastery_wall_connector_exit"],
  tower_pool: ["a"],
  tower_tower_pool: ["hf_mzs/monastery/monastery_tower"],
  tower_base_pool: ["hf_mzs/monastery/monastery_tower_base"],
  tower_middle_pool: ["hf_mzs/monastery/monastery_tower_middle"],
  tower_top_pool: ["hf_mzs/monastery/monastery_tower_top"],
  tower_path_pool: ["a"],
  for_tower_path_pool: ["a"],
  tower_door_path_pool: ["a"],
  windows_pool: [
    "hf_mzs/monastery/monastery_tower_blank",
    "hf_mzs/monastery/monastery_tower_window_short",
    "hf_mzs/monastery/monastery_tower_window_tall",
    "hf_mzs/monastery/monastery_tower_window1",
  ],
  room_pool: ["a"],
  room_no_decor_pool: ["a"],
  room_path_pool: ["a"],
  room_path_pool2: ["a"],
  room_expansion_pool: ["hf_mzs/monastery/monastery_room_extension"],
  for_room_windows_pool: ["a"],
  room_windows_pool: ["a"],
  path_pool: ["a"],
  door_pool: ["hf_mzs/monastery/dark_oak_door"],
  door_pool2: ["hf_mzs/monastery/dark_oak_door"],
  deepslate_base_pool: ["a"],
  bluff_spawn: ["a"],
  hanging_roots_pool: ["hf_mzs/monastery/monastery_hanging_roots"],
  stairs_pool: ["a"],
  entrance_stairs_pool: ["a"],
  //Interior
  //Tower Interior
  interior_wall_pool: ["a"],
  interior_wall_small_pool: ["a"],
  tower_stairs1_pool: ["hf_mzs/monastery/interior/monastery_tower_stairs_1"],
  tower_stairs2_pool: ["hf_mzs/monastery/interior/monastery_tower_stairs_2"],
  //General
  banners_pool: ["hf_mzs/monastery/interior/monastery_banners"],
  //Bookshelf
  bookshelf_pool: ["hf_mzs/monastery/interior/monastery_bookshelf"],
  bookshelf_pool2: ["hf_mzs/monastery/interior/monastery_bookshelf_2"],
  bookshelf_pool3: ["hf_mzs/monastery/interior/monastery_bookshelf_3"],
  bookshelf_pool4: ["hf_mzs/monastery/interior/monastery_bookshelf_4"],
  desk_pool: ["hf_mzs/monastery/interior/monastery_desk"],
  desk_pool2: ["hf_mzs/monastery/interior/monastery_desk_2"],
  desk_pool3: ["hf_mzs/monastery/interior/monastery_desk_3"],
  desk_pool4: ["hf_mzs/monastery/interior/monastery_desk_4"],
  gong_pool: ["hf_mzs/monastery/interior/monastery_gong"],
  spawner_pool: ["hf_mzs/monastery/monastery_bluff"],
  //Storage
  barrels_pool: ["hf_mzs/monastery/interior/monastery_barrels"],
  barrels_pool2: ["hf_mzs/monastery/interior/monastery_barrels_2"],
  barrels_pool3: ["hf_mzs/monastery/interior/monastery_barrels_3"],
  barrels_pool4: ["hf_mzs/monastery/interior/monastery_barrels_4"],
  shelf_pool: ["hf_mzs/monastery/interior/monastery_shelf"],
  //Dojo
  dummies_pool: ["hf_mzs/monastery/interior/monastery_dummies"],
  dummies_pool2: ["hf_mzs/monastery/interior/monastery_dummies_2"],
  weapons_pool: ["hf_mzs/monastery/interior/monastery_weapons"],
  punching_bag_wall_pool: ["hf_mzs/monastery/interior/monastery_punching_bag_wall"],
  training_post_wall_pool: ["hf_mzs/monastery/interior/monastery_training_post_wall"],
  //Room Interior
  interior_wall_corner_pool: ["a"],
  interior_wall_middle_pool: ["a"],
  interior_center_pool: ["a"],
  interior_center_base_pool: ["a"],
  room_stairs1_pool: ["hf_mzs/monastery/interior/monastery_room_stairs_1"],
  room_stairs2_pool: ["hf_mzs/monastery/interior/monastery_room_stairs_2"],
  //General
  corner_elevated_pool: ["hf_mzs/monastery/interior/monastery_corner_elevated"],
  landing_pool: ["hf_mzs/monastery/interior/monastery_landing"],
  partition_pool: ["hf_mzs/monastery/interior/monastery_partition"],
  //Dojo
  shrine_pool: ["hf_mzs/monastery/interior/monastery_shrine"],
  statue_center_pool: ["hf_mzs/monastery/interior/monastery_statue_center"],
  statue_pool: ["hf_mzs/monastery/interior/monastery_statue"],
  dojo_pool: ["hf_mzs/monastery/interior/monastery_dojo"],
};

const translateRotation = {
  down: 1,
  up: 0,
  north: 3,
  south: 2,
  west: 5,
  east: 4,
};
/**
 *
 * @param {mc.Structure} structure
 * @param {Number} blockRotation
 */
function structurePos(structure, blockRotation, rotItem, offset, offset2) {
  let rot = 0;
  let xOff = 0;
  let yOff = 0;
  let zOff = 0;
  let offSet = offset ?? 0;

  switch (blockRotation) {
    case 0: // Down
      rot = 0 + rotItem;
      yOff = -structure.size.y + offSet + offset2.y;
      xOff = -structure.size.x / 2 + offset2.x;
      zOff = -structure.size.z / 2 + offset2.z;
      break;
    case 1: // Up
      rot = 0 + rotItem;
      yOff = offSet + offset2.y;
      xOff = -structure.size.x / 2 + offset2.x;
      zOff = -structure.size.z / 2 + offset2.z;
      break;
    case 2: // North
      rot = 180 + rotItem;
      zOff = -(structure.size.z + offSet + offset2.z - 2);
      xOff = -structure.size.x / 2 + 1 + offset2.x;
      yOff = offset2.y;
      break;
    case 3: // South
      rot = 0 + rotItem;
      zOff = offSet + offset2.z - 1;
      xOff = -structure.size.x / 2 - offset2.x + 1;
      yOff = offset2.y;
      break;
    case 4: // West
      rot = 90 + rotItem;
      xOff = -(structure.size.x + offSet + offset2.z - 2);
      zOff = -structure.size.z / 2 - offset2.x + 1;
      yOff = offset2.y;
      break;
    case 5: // East
      rot = 270 + rotItem;
      xOff = offSet + offset2.z - 1;
      zOff = -structure.size.z / 2 + offset2.x + 1;
      yOff = offset2.y;
      break;
  }
  if (rot > 360) {
    rot -= 360;
  }
  return { rot: rot, xOff: xOff, yOff: yOff, zOff: zOff };
}
function roofOffset(blockRotation) {
  let xOff = 0;
  let yOff = 0;
  let zOff = 0;

  switch (blockRotation) {
    case 2: // North
      zOff = -4;
      xOff = -5;
      break;
    case 3: // South
      zOff = -5;
      xOff = -4;
      break;
    case 4: // West
      xOff = -4;
      zOff = -4;
      break;
    case 5: // East
      xOff = -5;
      zOff = -5;
      break;
  }
  return { xOff: xOff, yOff: yOff, zOff: zOff };
}
function structureBlockList() {
  const blockList = [
    "minecraft:dark_oak_double_slab",
    "hf_mzs:raked_sand",
    "minecraft:polished_diorite",
    "minecraft:red_concrete",
    "minecraft:yellow_concrete",
    "minecraft:stripped_birch_log",
    "minecraft:cobbled_deepslate",
    "minecraft:polished_deepslate",
    "minecraft:white_concrete",
    "minecraft:dark_oak_slab",
    "minecraft:lantern",
    "minecraft:dark_oak_trapdoor",
    "minecraft:birch_fence",
    "minecraft:dark_oak_fence",
    "minecraft:birch_fence_gate",
    "minecraft:dark_oak_fence_gate",
    "minecraft:dark_oak_stairs",
    "minecraft:dark_oak_planks",
    "minecraft:barrel",
    "minecraft:stripped_dark_oak_log",
    "minecraft:birch_trapdoor",
    "minecraft:diorite",
    "minecraft:diorite_wall",
    "minecraft:birch_slab",
    "minecraft:birch_planks",
  ];
  return blockList;
}
export function placeJigsawBlock(event) {
  const { block } = event;
  if (block.typeId === "hf_mzs:custom_jigsaw") {
    const loc = block.location;
    loc.x = Math.round(loc.x) + 0.5;
    loc.y = Math.round(loc.y) + 0.5;
    loc.z = Math.round(loc.z) + 0.5;
    block.dimension.runCommand(
      `/summon hf_mzs:custom_jigsaw_util ${loc.x} ${loc.y} ${loc.z} 0 0 minecraft:entity_spawned "Target Pool | Turns Into | Type | Offset | Tick Delay | Rotation"`
    );

    const blockRotation = block.permutation.getState("minecraft:facing_direction");
    const newRotation = translateRotation[blockRotation];
    block.setPermutation(mc.BlockPermutation.resolve("minecraft:barrel", { facing_direction: newRotation }));
  }
}

export function removeJigsaw(event) {
  if (event.id === "hf_mzs:remove_jigsaw") {
    const entity = event.sourceEntity;
    const block = entity.dimension.getBlock(entity.location);
    block.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
    entity.remove();
  }
}

export function placeJigsawPiece(event) {
  if (event.id === "hf_mzs:trigger_jigsaw_placement") {
    const entity = event.sourceEntity;

    const block = entity.dimension.getBlock(entity.location);

    if (block.typeId === "minecraft:barrel") {
      const inventory = block.getComponent("minecraft:inventory");
      if (inventory) {
        const pool = inventory.container.getItem(0)?.nameTag;

        if (!pool || !poolManager[pool]) {
          mc.world.sendMessage(`Invalid jigsaw pool at: ${entity.location.x} ${entity.location.y} ${entity.location.z}`);
          block.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
          entity.remove();
          return;
        }
        const replaceMaterial = inventory.container.getItem(1)?.typeId || "minecraft:air";

        if (!mc.BlockTypes.get(replaceMaterial)) {
          mc.world.sendMessage(`Invalid jigsaw replace material at: ${entity.location.x} ${entity.location.y} ${entity.location.z}`);
          block.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
          entity.remove();
          return;
        }

        const type = inventory.container.getItem(2)?.nameTag;
        const offset = inventory.container.getItem(3)?.amount || 0;
        const delay = inventory.container.getItem(4)?.amount || 0;
        let rotItem = Number(inventory.container.getItem(5)?.nameTag);
        if (!rotItem) {
          rotItem = 0;
        }

        mc.system.runTimeout(() => {
          let piece;
          if (type) {
            if (type === `randomize`) {
              piece = poolManager.randomize(pool, 0, block, rotItem, 0, entity);
            }
          } else {
            piece = poolManager.getRandom(pool, 0, block, rotItem, { x: 0, y: 0, z: 0 }, entity);
          }
          if (pool === `tower_pool` || pool === `deepslate_base_pool` || pool === `room_pool` || pool === `bluff_spawn` || pool === `room_windows_pool`) {
            try {
              inventory.container.clearAll();
            } catch { }
            block.setPermutation(mc.BlockPermutation.resolve(replaceMaterial));
            return;
          }

          let rot = 0;
          let pieceRot = piece?.rot ?? 0;
          let xOff = 0;
          let yOff = 0;
          let zOff = 0;
          const blockRotation = block.permutation.getState("facing_direction");
          if (pool !== `tower_pool` && pool !== `deepslate_base_pool` && pool !== `room_pool` && pool !== `bluff_spawn` && pool !== `room_windows_pool`) {
            try {
              switch (blockRotation) {
                case 0: // Down
                  rot = 0 + rotItem + pieceRot;
                  yOff = -piece.structure.size.y + offset + piece.offset.y;
                  xOff = -piece.structure.size.x / 2 + piece.offset.x;
                  zOff = -piece.structure.size.z / 2 + piece.offset.z;
                  break;
                case 1: // Up
                  rot = 0 + rotItem + pieceRot;
                  yOff = offset + piece.offset.y;
                  xOff = -piece.structure.size.x / 2 + piece.offset.x;
                  zOff = -piece.structure.size.z / 2 + piece.offset.z;
                  break;
                case 2: // North
                  rot = 180 + rotItem + pieceRot;
                  zOff = -(piece.structure.size.z + offset + piece.offset.z - 1);
                  xOff = -piece.structure.size.x / 2 + piece.offset.x;
                  yOff = piece.offset.y;
                  break;
                case 3: // South
                  rot = 0 + rotItem + pieceRot;
                  zOff = offset + piece.offset.z;
                  xOff = -piece.structure.size.x / 2 - piece.offset.x;
                  yOff = piece.offset.y;
                  break;
                case 4: // West
                  rot = 90 + rotItem + pieceRot;
                  xOff = -(piece.structure.size.x + offset + piece.offset.z - 1);
                  zOff = -piece.structure.size.z / 2 - piece.offset.x;
                  yOff = piece.offset.y;
                  break;
                case 5: // East
                  rot = 270 + rotItem + pieceRot;
                  xOff = offset + piece.offset.z;
                  zOff = -piece.structure.size.z / 2 + piece.offset.x;
                  yOff = piece.offset.y;
                  break;
              }
              if (
                piece?.name === `hf_mzs/monastery/interior/monastery_landing` ||
                piece?.name === `hf_mzs/monastery/interior/monastery_statue_center` ||
                piece?.name === `hf_mzs/monastery/interior/monastery_dojo`
              ) {
                rot = 0;
              }
              const windows_pool = [
                "hf_mzs/monastery/monastery_tower_blank",
                "hf_mzs/monastery/monastery_tower_window_short",
                "hf_mzs/monastery/monastery_tower_window_tall",
                "hf_mzs/monastery/monastery_tower_window1",
              ];
              if (windows_pool.includes(piece?.name)) {
                if (blockRotation === 5) {
                  //East
                  rot = 90;
                } else if (blockRotation === 2) {
                  //North
                  rot = 0;
                }
              }
              if (piece?.name === `hf_mzs/monastery/interior/monastery_tower_stairs_1` || piece?.name === `hf_mzs/monastery/interior/monastery_tower_stairs_2`) {
                if (blockRotation === 5) {
                  //East
                  rot = 270;
                }
              }
            } catch { }
          } else return;
          //mc.world.sendMessage(`${inventory.container} ${entity.location.x} ${entity.location.y} ${entity.location.z}`);

          if (rot > 360) {
            rot -= 360;
          }
          let mirrored = "None";
          const rotName = structureManager.toStructureRot.get(rot);
          try {
            inventory.container.clearAll();
          } catch { }
          if (!piece) return;

          if (piece?.name === "hf_mzs/monastery/monastery_wall_straight" || piece?.name === "hf_mzs/monastery/monastery_wall_gap") {
            if (blockRotation === 2) {
              //North
              zOff = -(piece.structure.size.z + offset + piece.offset.z - 2);
              if (piece.name === "hf_mzs/monastery/monastery_wall_gap") {
                zOff = -(piece.structure.size.z + offset + piece.offset.z - 5);
                xOff = -piece.structure.size.x;
              }
            }
            if (blockRotation === 3) {
              //South
              if (piece.name === "hf_mzs/monastery/monastery_wall_gap") {
                xOff = -piece.structure.size.x;
              }
            }
          }
          if (
            piece?.name === `hf_mzs/monastery/monastery_wall_connector` ||
            piece?.name === "hf_mzs/monastery/monastery_wall_connector_end" ||
            piece?.name === "hf_mzs/monastery/monastery_wall_connector_exit"
          ) {
            if (blockRotation === 2) {
              //North
              zOff = -piece.structure.size.z + offset + piece.offset.z + 5;
              xOff = -piece.structure.size.x;
              if (piece.name === "hf_mzs/monastery/monastery_wall_connector_end") {
                xOff = -piece.structure.size.x + 1;
              }
            }
            if (blockRotation === 3) {
              //South
              xOff = -piece.structure.size.x;
              if (piece.name === "hf_mzs/monastery/monastery_wall_connector_end") {
                xOff = -piece.structure.size.x + 1;
              }
            }
          }
          if (piece?.name === `hf_mzs/monastery/monastery_wall_corner`) {
            const random = Math.random();
            if (random < 0.5) {
              mirrored = "X";
            }
            if (blockRotation === 2) {
              zOff = -(piece.structure.size.z + offset + piece.offset.z - 2);
            }
          }
          if (piece?.name === `hf_mzs/monastery/monastery_wall_accent`) {
            if (blockRotation === 4) {
              xOff += 1;
            }
          }
          if (piece?.name === `hf_mzs/monastery/interior/monastery_tower_stairs_1` || piece?.name === `hf_mzs/monastery/interior/monastery_room_stairs_1`) {
            switch (blockRotation) {
              case 2: //North
                if (piece?.name === `hf_mzs/monastery/interior/monastery_room_stairs_1`) {
                  break;
                } else {
                  xOff += 1;
                  break;
                }
              case 4: //West
                if (piece?.name === `hf_mzs/monastery/interior/monastery_tower_stairs_1`) {
                  xOff += 3;
                  zOff -= 2;
                  break;
                } else {
                  xOff += 2;
                  zOff -= 1;
                  break;
                }
              case 5:
                zOff -= 1;
            }
          }
          if (piece?.name === `hf_mzs/monastery/interior/monastery_tower_stairs_2`) {
            if (blockRotation === 4) {
              xOff -= 2;
              zOff += 1;
            }
            if (blockRotation === 5) {
              zOff += 1;
            }
          }
          if (piece?.name === `hf_mzs/monastery/interior/monastery_room_stairs_2`) {
            switch (blockRotation) {
              case 2: //North
                xOff += 2;
                break;
              case 3: //South
                xOff -= 1;
                break;
              case 4: //West
                xOff += 3;
                zOff -= 3;
                break;
            }
          }
          if (piece?.name === `hf_mzs/monastery/interior/monastery_corner_elevated`) {
            if (blockRotation === 4) {
              //West
              zOff += 1;
            }
            if (blockRotation === 3) {
              //South
              xOff += 1;
            }
          }
          if (piece?.name === `hf_mzs/monastery/interior/monastery_statue`) {
            if (blockRotation === 4) {
              //West
              xOff += 1;
            }
          }

          const start = {
            x: entity.location.x + xOff,
            y: entity.location.y + yOff,
            z: entity.location.z + zOff,
          };
          const allWindowsPool = [
            "hf_mzs/monastery/monastery_tower_blank",
            "hf_mzs/monastery/monastery_tower_window_short",
            "hf_mzs/monastery/monastery_tower_window_tall",
            "hf_mzs/monastery/monastery_tower_window1",
            "hf_mzs/monastery/monastery_tower_window1_center"
          ];

          if (allWindowsPool.includes(piece?.name)) {
            const dim = entity.dimension;
            mc.system.runTimeout(() => {
              mc.world.structureManager.place(piece?.structure, dim, start, {
                animationMode: mc.StructureAnimationMode.None,
                rotation: rotName,
                includeEntities: true,
                mirror: mirrored,
              });
            }, 40)
          } else {
            mc.world.structureManager.place(piece?.structure, entity.dimension, start, {
              animationMode: mc.StructureAnimationMode.None,
              rotation: rotName,
              includeEntities: true,
              mirror: mirrored,
            });
          }

          mc.system.runTimeout(() => {
            if (
              piece.name === `hf_mzs/monastery/monastery_wall_accent` ||
              piece.name === `hf_mzs/monastery/interior/monastery_shelf` ||
              piece.name === `hf_mzs/monastery/interior/monastery_landing`
            ) {
              const center = {
                x: start.x + piece.structure.size.x / 2,
                y: start.y,
                z: start.z + piece.structure.size.z / 2,
              };
              const trapdoorsList = ["minecraft:jungle_trapdoor", "minecraft:dark_oak_trapdoor"];
              trapdoorsList.forEach((block) => {
                getTrapdoors();
                async function getTrapdoors() {
                  const blocksFound = await selectors.GetBlockInRadius(
                    center,
                    block,
                    vector.getCenterFromXYZ(piece.structure.size.x, piece.structure.size.y, piece.structure.size.z),
                    mc.world.getDimension(entity?.dimension.id)
                  );
                  if (blocksFound.length > 0) {
                    blocksFound.forEach((pos) => {
                      const blockFound = entity.dimension.getBlock(pos);
                      let direction = blockFound.permutation.getState(`direction`);
                      switch (rotName) {
                        case "None":
                          break;
                        case "Rotate180":
                          if (piece.name === `hf_mzs/monastery/interior/monastery_shelf`) {
                            if (direction === 2) {
                              direction -= 1;
                            } else direction += 1;
                          } else direction += 1;
                          break;
                        case "Rotate90":
                          if (piece.name === `hf_mzs/monastery/interior/monastery_shelf`) {
                            direction += 1;
                          } else direction -= 3;
                          break;
                        case "Rotate270":
                          if (piece.name === `hf_mzs/monastery/interior/monastery_shelf`) {
                            if (direction === 0) {
                              direction += 2;
                            }
                          } else direction -= 1;
                          break;
                      }
                      blockFound.setPermutation(blockFound.permutation.withState(`direction`, direction));
                    });
                  }
                }
              });
            }
            block.dimension.runCommand(`/kill @e[type=item]`);
          }, 5);

          if (replaceMaterial.startsWith("minecraft:") && replaceMaterial.includes("_slab")) {
            block.setPermutation(mc.BlockPermutation.resolve(replaceMaterial, { "minecraft:vertical_half": "top" }));
          } else if (replaceMaterial.startsWith("minecraft:") && replaceMaterial.includes("stripped_")) {
            if (blockRotation === 3 || blockRotation === 2) {
              block.setPermutation(mc.BlockPermutation.resolve(replaceMaterial, { pillar_axis: "z" }));
            } else if (blockRotation === 5 || blockRotation === 4) {
              block.setPermutation(mc.BlockPermutation.resolve(replaceMaterial, { pillar_axis: "x" }));
            } else if (blockRotation === 0 || blockRotation === 1) {
              block.setPermutation(mc.BlockPermutation.resolve(replaceMaterial, { pillar_axis: "y" }));
            }
          } else {
            block.setPermutation(mc.BlockPermutation.resolve(replaceMaterial));
          }

          if (piece?.name === "hf_mzs/monastery/interior/monastery_landing" || piece?.name === "hf_mzs/monastery/monastery_room_extension") {
            block.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
          }
        }, delay);
      }
    }
  }
}
