import { EquipmentSlot, BlockPermutation, system } from "@minecraft/server";
import { getBlockTextures } from "../main.js";
import { guiTextureSelect } from "../gui/index.js";
const placeFenceComponent = {
  beforeOnPlayerPlace(e) {
    const { block, dimension, player } = e;
    const heldItem = player.getComponent("inventory").container.getItem(player.selectedSlotIndex);
    if (heldItem.typeId.includes("maca_probuilder:") && heldItem.typeId.includes("fence")) {
      e.cancel = true;
      const loc = block.location;
      const equipment = player.getComponent("equippable");
      const selectedItem = equipment.getEquipment(EquipmentSlot.Mainhand);
      let storedLore;
      if (selectedItem && selectedItem !== void 0) {
        storedLore = selectedItem.getLore()[0];
      } else {
        storedLore = player.getDynamicProperty("maca_probuilder:stored_lore");
      }
      system.runTimeout(() => {
        if (player.getGameMode() !== "creative") {
          if (selectedItem.amount > 1) {
            selectedItem.amount -= 1;
            equipment.setEquipment(EquipmentSlot.Mainhand, selectedItem);
          } else {
            equipment.setEquipment(EquipmentSlot.Mainhand, void 0);
          }
        }
        const belowBlock = block.below();
        if (belowBlock.typeId.includes("maca_probuilder:") && belowBlock.typeId.includes("fence")) {
          const belowConnections = getNeighborConnections(belowBlock);
          const belowConnectionCount = Object.values(belowConnections).filter(Boolean).length;
          if (belowBlock.typeId.includes("_corner") && e.face === "Up" || belowConnectionCount <= 1) {
            let cardinalDirection;
            if (belowBlock.typeId.includes("_corner")) {
              const belowBlockDirection = belowBlock.permutation.getState(
                "minecraft:cardinal_direction"
              );
              const rotation = player.getRotation();
              const rad = rotation.y * Math.PI / 180;
              const directionX = -Math.sin(rad);
              const directionZ = Math.cos(rad);
              let playerFacing;
              if (Math.abs(directionX) > Math.abs(directionZ)) {
                playerFacing = directionX > 0 ? "north" : "south";
              } else {
                playerFacing = directionZ > 0 ? "west" : "east";
              }
              let availableDirections;
              switch (belowBlockDirection) {
                case "north":
                  availableDirections = ["east", "south"];
                  break;
                case "south":
                  availableDirections = ["north", "west"];
                  break;
                case "east":
                  availableDirections = ["south", "west"];
                  break;
                case "west":
                  availableDirections = ["north", "east"];
                  break;
                default:
                  availableDirections = ["north", "east"];
              }
              if (belowBlockDirection === "west") {
                cardinalDirection = playerFacing === "north" || playerFacing === "south" ? "east" : "north";
              } else {
                if (playerFacing === "north" || playerFacing === "south") {
                  cardinalDirection = availableDirections.includes("east") ? "east" : "west";
                } else {
                  cardinalDirection = availableDirections.includes("south") ? "south" : "north";
                }
              }
            } else {
              const rotation = player.getRotation();
              const rad = rotation.y * Math.PI / 180;
              const directionX = -Math.sin(rad);
              const directionZ = Math.cos(rad);
              let playerFacing;
              if (Math.abs(directionX) > Math.abs(directionZ)) {
                playerFacing = directionX > 0 ? "west" : "east";
              } else {
                playerFacing = directionZ > 0 ? "north" : "south";
              }
              cardinalDirection = getOppositeDirection(playerFacing);
            }
            let blockPerm = BlockPermutation.resolve(
              resolveType(selectedItem, "_upwards")
            );
            blockPerm = blockPerm.withState(
              "minecraft:cardinal_direction",
              cardinalDirection
            );
            blockPerm = applyTexture(blockPerm, belowBlock, selectedItem);
            dimension.getBlock(loc).setPermutation(blockPerm);
            if (belowBlock.typeId.includes("_straight")) {
              let belowBlockPerm = BlockPermutation.resolve(
                resolveType(selectedItem, "_end")
              );
              belowBlockPerm = belowBlockPerm.withState(
                "minecraft:cardinal_direction",
                getOppositeDirection(cardinalDirection)
              );
              belowBlockPerm = applyTexture(
                belowBlockPerm,
                belowBlock,
                selectedItem
              );
              belowBlock.setPermutation(belowBlockPerm);
            }
          } else {
            placeFence(dimension, block, loc, player, storedLore, selectedItem);
          }
        } else {
          placeFence(dimension, block, loc, player, storedLore, selectedItem);
        }
        if (player.isSneaking) {
          const placedBlock = dimension.getBlock(loc);
          const validTextures = getBlockTextures(placedBlock).map((x) => x.name);
          guiTextureSelect(
            player,
            placedBlock,
            validTextures,
            "",
            validTextures.findIndex((x) => x === storedLore)
          );
        }
      });
    }
  }
};
function placeFence(dimension, block, loc, player, storedLore, item) {
  const connections = getNeighborConnections(block);
  let connectionCount = Object.values(connections).filter(Boolean).length;
  let fenceType;
  let cardinalDirection;
  const adjacentUpwardFence = Object.keys(connections).find(
    (dir) => connections[dir] && block[dir]().typeId.includes("fence_upwards")
  );
  switch (connectionCount) {
    case 0:
      fenceType = resolveType(item, "_post");
      break;
    case 1:
      fenceType = resolveType(item, "_end");
      if (adjacentUpwardFence) {
        const upwardFenceBlock = block[adjacentUpwardFence]();
        const upwardFenceDirection = upwardFenceBlock.permutation.getState(
          "minecraft:cardinal_direction"
        );
        if (adjacentUpwardFence === getOppositeDirection(upwardFenceDirection)) {
          cardinalDirection = getOppositeDirection(adjacentUpwardFence);
        } else {
          cardinalDirection = adjacentUpwardFence;
        }
      } else {
        cardinalDirection = Object.keys(connections).find(
          (dir) => connections[dir]
        );
      }
      break;
    case 2:
      if (adjacentUpwardFence) {
        fenceType = resolveType(item, "_end");
        const upwardFenceBlock = block[adjacentUpwardFence]();
        const upwardFenceDirection = upwardFenceBlock.permutation.getState(
          "minecraft:cardinal_direction"
        );
        const otherConnection = Object.keys(connections).find(
          (dir) => connections[dir] && dir !== adjacentUpwardFence
        );
        if (adjacentUpwardFence === getOppositeDirection(upwardFenceDirection)) {
          cardinalDirection = getOppositeDirection(adjacentUpwardFence);
        } else {
          cardinalDirection = otherConnection;
        }
      } else if (connections.north && connections.south || connections.east && connections.west) {
        fenceType = resolveType(item, "_straight");
        cardinalDirection = connections.north || connections.south ? "north" : "east";
      } else {
        fenceType = resolveType(item, "_corner");
        cardinalDirection = getCornerDirection(connections);
      }
      break;
    case 3:
      fenceType = resolveType(item, "_corner");
      cardinalDirection = getCornerDirection(connections);
      break;
    case 4:
      fenceType = resolveType(item, "_straight");
      cardinalDirection = "north";
      break;
    default:
      fenceType = resolveType(item, "_post");
  }
  const equipment = player.getComponent("equippable");
  const itemStack = equipment.getEquipment(EquipmentSlot.Mainhand);
  if (itemStack && itemStack !== void 0) {
    storedLore = itemStack.getLore()[0];
  } else {
    storedLore = player.getDynamicProperty("maca_probuilder:stored_lore");
  }
  let blockPerm = BlockPermutation.resolve(fenceType);
  if (storedLore !== void 0) {
    const textures = getBlockTextures(BlockPermutation.resolve(fenceType));
    let index = textures.findIndex(
      (x) => x.name === storedLore || x.item === storedLore
    );
    if (index !== -1) {
      blockPerm = blockPerm.withState(
        "maca_probuilder:texture_bit_0",
        index % 16
      );
      if (textures.length > 16 && !item.typeId.includes("wooden")) {
        blockPerm = blockPerm.withState(
          "maca_probuilder:texture_bit_1",
          Math.floor(index / 16)
        );
      }
    }
  }
  if (fenceType === resolveType(item, "_straight")) {
    blockPerm = blockPerm.withState(
      "maca_probuilder:axis_rotation",
      directionToXY(cardinalDirection)
    );
  } else if (fenceType.includes("_fence_end") || fenceType.includes("_fence_corner")) {
    blockPerm = blockPerm.withState(
      "minecraft:cardinal_direction",
      cardinalDirection
    );
  }
  dimension.getBlock(loc).setPermutation(blockPerm);
  updateAdjacentBlocks(block, connections, player);
}
function updateAdjacentBlocks(block, connections, player) {
  const diagonalEnabled = player.getDynamicProperty("diagonalMode") === false;
  const directions = ["north", "south", "east", "west"];
  directions.forEach((dir) => {
    if (connections[dir]) {
      const adjacentBlock = block[dir]();
      if (adjacentBlock.typeId.includes("fence_upwards")) {
        const currentDirection = adjacentBlock.permutation.getState(
          "minecraft:cardinal_direction"
        );
        if (getOppositeDirection(dir) === currentDirection) {
          return;
        }
      }
      const neighborConnections = getNeighborConnections(adjacentBlock);
      let newFenceType;
      let cardinalDirection;
      const filteredConnections = { ...neighborConnections };
      Object.keys(filteredConnections).forEach((direction) => {
        if (adjacentBlock[direction]().typeId.includes("fence_upwards")) {
          filteredConnections[direction] = false;
        }
      });
      const connectionCount = Object.values(filteredConnections).filter(Boolean).length;
      if (adjacentBlock.typeId.includes("wooden_fence")) {
        const possibleDirections = ["north", "south", "east", "west"];
        for (const checkDir of possibleDirections) {
          const secondBlock = adjacentBlock[checkDir]();
          const thirdBlock = secondBlock[checkDir]();
          const blockPermutation2 = block.permutation.getState("minecraft:cardinal_direction") || block.permutation.getState("maca_probuilder:axis_rotation");
          const adjacentBlockPermutation2 = adjacentBlock.permutation.getState(
            "minecraft:cardinal_direction"
          ) || adjacentBlock.permutation.getState("maca_probuilder:axis_rotation");
          if (blockPermutation2 === adjacentBlockPermutation2 && adjacentBlock.typeId.includes("_end") && secondBlock.typeId.includes("wooden_fence") && secondBlock.typeId.endsWith("_straight") && thirdBlock.typeId.includes("wooden_fence") && thirdBlock.typeId.endsWith("_straight")) {
            let postBlockPerm = BlockPermutation.resolve(
              resolveType(secondBlock, "_straight_post")
            );
            postBlockPerm = postBlockPerm.withState(
              "maca_probuilder:axis_rotation",
              directionToXY(checkDir)
            );
            postBlockPerm = applyTexture(
              postBlockPerm,
              secondBlock,
              secondBlock
            );
            secondBlock.setPermutation(postBlockPerm);
            let straightBlockPerm = BlockPermutation.resolve(
              resolveType(adjacentBlock, "_straight")
            );
            straightBlockPerm = straightBlockPerm.withState(
              "maca_probuilder:axis_rotation",
              directionToXY(checkDir)
            );
            straightBlockPerm = applyTexture(
              straightBlockPerm,
              adjacentBlock,
              adjacentBlock
            );
            adjacentBlock.setPermutation(straightBlockPerm);
            return;
          }
        }
      }
      const blockPermutation = block.permutation.getState("minecraft:cardinal_direction") || block.permutation.getState("maca_probuilder:axis_rotation");
      const adjacentBlockPermutation = adjacentBlock.permutation.getState("minecraft:cardinal_direction") || adjacentBlock.permutation.getState("maca_probuilder:axis_rotation");
      const isCorner = (blockPermutation === "east" || blockPermutation === "west" || blockPermutation === "x") && (adjacentBlockPermutation === "north" || adjacentBlockPermutation === "south" || adjacentBlockPermutation === "z") || (blockPermutation === "north" || blockPermutation === "south" || blockPermutation === "z") && (adjacentBlockPermutation === "east" || adjacentBlockPermutation === "west" || adjacentBlockPermutation === "x");
      if (isCorner) {
        if (connectionCount >= 2) {
          newFenceType = resolveType(adjacentBlock, "_corner");
          cardinalDirection = getCornerDirection(filteredConnections);
        } else {
          newFenceType = resolveType(adjacentBlock, "_end");
          cardinalDirection = getOppositeDirection(dir);
        }
      } else {
        switch (connectionCount) {
          case 1:
            newFenceType = resolveType(adjacentBlock, "_end");
            cardinalDirection = getOppositeDirection(dir);
            break;
          case 2:
            if (filteredConnections.north && filteredConnections.south || filteredConnections.east && filteredConnections.west) {
              newFenceType = resolveType(adjacentBlock, "_straight");
              cardinalDirection = filteredConnections.north || filteredConnections.south ? "north" : "east";
            } else {
              newFenceType = resolveType(adjacentBlock, "_corner");
              cardinalDirection = getCornerDirection(filteredConnections);
            }
            break;
          case 3:
            newFenceType = resolveType(adjacentBlock, "_corner");
            cardinalDirection = getCornerDirection(filteredConnections);
            break;
          case 4:
            newFenceType = resolveType(adjacentBlock, "_straight");
            cardinalDirection = "north";
            break;
          default:
            return;
        }
      }
      if (adjacentBlock.typeId.includes(newFenceType)) {
        return;
      }
      if (newFenceType.includes("_corner") && diagonalEnabled && adjacentBlock.typeId.includes("iron_fence")) {
        const wasUpdated = updateDiagonalFence(adjacentBlock);
        if (wasUpdated) {
          return;
        }
      }
      let blockPerm = BlockPermutation.resolve(newFenceType);
      blockPerm = applyTexture(blockPerm, adjacentBlock, adjacentBlock);
      if (newFenceType.includes("_straight")) {
        blockPerm = blockPerm.withState(
          "maca_probuilder:axis_rotation",
          directionToXY(cardinalDirection)
        );
      } else {
        blockPerm = blockPerm.withState(
          "minecraft:cardinal_direction",
          cardinalDirection
        );
      }
      adjacentBlock.setPermutation(blockPerm);
      if (diagonalEnabled) {
        updateDiagonalFence(block);
      }
    }
  });
}
function applyTexture(blockPerm, block, item) {
  const currentTextureBit0 = block.permutation.getState("maca_probuilder:texture_bit_0") || 0;
  const currentTextureBit1 = block.permutation.getState("maca_probuilder:texture_bit_1") || 0;
  blockPerm = blockPerm.withState(
    "maca_probuilder:texture_bit_0",
    currentTextureBit0
  );
  if (!item.typeId.includes("wooden")) {
    blockPerm = blockPerm.withState(
      "maca_probuilder:texture_bit_1",
      currentTextureBit1
    );
  }
  return blockPerm;
}
function getNeighborConnections(block) {
  return {
    north: isFence(block.north()),
    south: isFence(block.south()),
    east: isFence(block.east()),
    west: isFence(block.west())
  };
}
function isFence(block) {
  return block.typeId.includes("maca_probuilder:") && (block.typeId.includes("fence") || block.typeId.includes("fence_upwards"));
}
function getCornerDirection(connections) {
  if (connections.north && connections.east)
    return "east";
  if (connections.north && connections.west)
    return "north";
  if (connections.south && connections.east)
    return "south";
  if (connections.south && connections.west)
    return "west";
  return "north";
}
function getOppositeDirection(direction) {
  switch (direction) {
    case "north":
      return "south";
    case "south":
      return "north";
    case "east":
      return "west";
    case "west":
      return "east";
    default:
      return direction;
  }
}
function directionToXY(direction) {
  switch (direction) {
    case "north":
    case "south":
      return "z";
    case "east":
    case "west":
      return "x";
    default:
      return "x";
  }
}
function resolveType(block, type) {
  const prefix = "maca_probuilder:";
  let blockPrefix;
  if (block.typeId.includes("wooden_fence")) {
    blockPrefix = "wooden_fence";
  } else if (block.typeId.includes("iron_fence")) {
    blockPrefix = "iron_fence";
  }
  const fullTypeId = `${prefix}${blockPrefix}${type}`;
  return fullTypeId;
}
function updateDiagonalFence(block) {
  if (!block.typeId.includes("iron_fence")) {
    return false;
  }
  const directions = ["north", "south", "east", "west"];
  for (const dir of directions) {
    const adjacentBlock = block[dir]();
    if (adjacentBlock.typeId.includes("iron_fence_corner")) {
      const adjacentDirection = adjacentBlock.permutation.getState("minecraft:cardinal_direction");
      const endType = resolveType(block, "_end");
      let endPerm = BlockPermutation.resolve(endType);
      const newDirection = getPerpendicularDirection(adjacentDirection, dir);
      const oppositeNewDirection = getOppositeDirection(newDirection);
      endPerm = endPerm.withState(
        "minecraft:cardinal_direction",
        oppositeNewDirection
      );
      endPerm = applyTexture(endPerm, block, block);
      block.setPermutation(endPerm);
      const adjacentDiagonalType = resolveType(adjacentBlock, "_diagonal");
      let adjacentDiagonalPerm = BlockPermutation.resolve(adjacentDiagonalType);
      adjacentDiagonalPerm = adjacentDiagonalPerm.withState(
        "minecraft:cardinal_direction",
        adjacentDirection
      );
      adjacentDiagonalPerm = applyTexture(
        adjacentDiagonalPerm,
        adjacentBlock,
        adjacentBlock
      );
      adjacentBlock.setPermutation(adjacentDiagonalPerm);
      return true;
    }
  }
  return false;
}
function getPerpendicularDirection(adjacentDirection, placementDirection) {
  const directionPairs = {
    "north": { "east": "west", "west": "east" },
    "south": { "east": "west", "west": "east" },
    "east": { "north": "south", "south": "north" },
    "west": { "north": "south", "south": "north" }
  };
  return directionPairs[adjacentDirection][placementDirection] || adjacentDirection;
}
export {
  getOppositeDirection,
  placeFenceComponent
};
