import { world, system, BlockTypes, Player } from "@minecraft/server";
import { playerData } from "./exchanger";
import { setPerms, getButtonDirection, getLeverDirection } from "./claw";
import { setBlock, getBlockTextures } from "./main";
import { guiTextureSelect } from "./gui/index";
const eventQueue = [];
const playerInventorySnapshots = /* @__PURE__ */ new Map();
const cooldownMap = /* @__PURE__ */ new Map();
const clickIntervals = /* @__PURE__ */ new Map();
const twoTall = /* @__PURE__ */ new Set([
  "minecraft:oak_door",
  "minecraft:spruce_door",
  "minecraft:acacia_door",
  "minecraft:jungle_door",
  "minecraft:mangrove_door",
  "minecraft:warped_door",
  "minecraft:birch_door",
  "minecraft:crimson_door",
  "minecraft:dark_oak_door",
  "minecraft:pale_oak_door",
  "minecraft:cherry_door",
  "minecraft:bamboo_door",
  "minecraft:iron_door",
  "minecraft:sunflower",
  "minecraft:lilac",
  "minecraft:rose_bush",
  "minecraft:peony",
  "minecraft:pitcher_plant"
]);
world.afterEvents.itemStartUse.subscribe((e) => {
  const { source: player, itemStack } = e;
  if (!(player instanceof Player))
    return;
  if (itemStack.typeId !== "maca_probuilder:randomizer")
    return;
  if (player.isSneaking)
    return;
  const range = player.hasTag("maca_pb:claw_active") ? 32 : 8;
  const raycast = player.getBlockFromViewDirection({ maxDistance: range });
  if (!raycast || !raycast.block)
    return;
  const block = raycast.block;
  eventQueue.push({ player, block, item: itemStack, blockFace: raycast.face, faceLocation: raycast.faceLocation });
  if (clickIntervals.has(player.id))
    return;
  clickInterval(player, itemStack);
});
function clickInterval(player, itemStack) {
  const interval = system.runInterval(() => {
    const range = player.hasTag("maca_pb:claw_active") ? 32 : 8;
    const raycast = player.getBlockFromViewDirection({ maxDistance: range });
    if (!raycast || !raycast.block)
      return;
    const block = raycast.block;
    eventQueue.push({ player, block, item: itemStack, blockFace: raycast.face, faceLocation: raycast.faceLocation });
  }, 4);
  clickIntervals.set(player.id, interval);
}
world.afterEvents.itemStopUse.subscribe((event2) => {
  const player = event2.source;
  const item = event2.itemStack;
  if (item?.typeId !== "maca_probuilder:randomizer")
    return;
  if (!clickIntervals.has(player.id))
    return;
  const interval = clickIntervals.get(player.id);
  system.clearRun(interval);
  clickIntervals.delete(player.id);
  return;
});
function processQueue() {
  const eventsToProcess = eventQueue.splice(0, eventQueue.length);
  for (const event2 of eventsToProcess) {
    handleItemUseOn(event2.player, event2.block, event2.item, event2.blockFace, event2.faceLocation);
  }
  system.runTimeout(processQueue, 2);
}
function handleItemUseOn(player, block, item, blockFace, faceLocation) {
  const inventory = player.getComponent("inventory");
  if (item.typeId !== "maca_probuilder:randomizer")
    return;
  if (!playerData.has(player.id)) {
    playerData.set(player.id, { setBlock: {}, intervalId: 0, highlightEntity: {}, permutations: void 0, clawSwap: false, randomSwap: event.itemStack.typeId === "maca_probuilder:exchange", blockItems: [], clickedBlockLocation: {}, clickedBlockFace: void 0, cachedHotbar: [] });
  }
  const data = playerData.get(player.id);
  data.clickedBlockLocation = {
    x: block.location.x,
    y: block.location.y,
    z: block.location.z
  };
  data.clickedBlockFace = blockFace;
  if (hasInventoryChanged(player)) {
    updateHotbarAndBlockItems(player, inventory, data);
  }
  if (data.blockItems.size === 0)
    return;
  const randomIndex = Math.floor(Math.random() * data.blockItems.size);
  const selectedSlot = Array.from(data.blockItems.keys())[randomIndex];
  const selectedBlock = data.blockItems.get(selectedSlot);
  let newBlockLocation = calculateNewBlockLocation(data);
  if (data.randomSwap) {
    newBlockLocation = block.location;
  }
  try {
    const newBlock = player.dimension.getBlock(newBlockLocation);
    if (newBlock.typeId.includes("door") && !newBlock.typeId.includes("iron") && !data.randomSwap && !player.isSneaking)
      return;
    const oldId = newBlock.typeId;
    if (newBlock && (newBlock.typeId === "minecraft:air" || data.randomSwap)) {
      if (data.randomSwap && twoTall.has(newBlock.typeId)) {
        if (newBlock.below().typeId === newBlock.typeId) {
          newBlock.below().setType("air");
        }
        if (newBlock.above().typeId === newBlock.typeId) {
          newBlock.above().setType("air");
        }
      }
      const newType = selectedBlock.typeId.includes("minecraft:") ? selectedBlock.typeId.split(":")[1] : selectedBlock.typeId;
      if (selectedBlock?.typeId === "minecraft:lever") {
        const leverDirection = getLeverDirection(blockFace, player);
        player.runCommand(`setblock ${newBlock.location.x} ${newBlock.location.y} ${newBlock.location.z} ${newType} ["lever_direction"="${leverDirection}"]`);
      } else if (selectedBlock?.typeId.includes("_button")) {
        const buttonDirection = getButtonDirection(blockFace);
        player.runCommand(`setblock ${newBlock.location.x} ${newBlock.location.y} ${newBlock.location.z} ${newType} ["facing_direction"=${buttonDirection}]`);
      } else {
        player.runCommand(`setblock ${newBlock.location.x} ${newBlock.location.y} ${newBlock.location.z} ${newType}`);
        const blockPerms = newBlock.permutation.getAllStates();
        setPerms(blockPerms, player, newBlock, blockFace, faceLocation);
      }
      updateInventoryAfterPlacement(player, inventory, selectedSlot, selectedBlock, data, oldId);
      snapshotPlayerInventory(player);
      if (selectedBlock.typeId.includes("maca_probuilder:")) {
        if (selectedBlock && selectedBlock != void 0) {
          var storedLore = selectedBlock.getLore()[0];
        } else {
          storedLore = player.getDynamicProperty("maca_probuilder:stored_lore");
        }
        if (player.isSneaking) {
          const validTextures = getBlockTextures(newBlock).map((x) => x.name);
          guiTextureSelect(player, newBlock, validTextures, "", validTextures.findIndex((x) => x === storedLore));
        }
        if (storedLore != void 0)
          setBlock(player, newBlock, storedLore, false);
      }
    }
  } catch (error) {
    console.warn(error);
  }
  data.clickedBlockLocation = null;
  data.clickedBlockFace = null;
}
function snapshotPlayerInventory(player) {
  const inventory = player.getComponent("inventory");
  const inventorySnapshot = /* @__PURE__ */ new Map();
  for (let i = 0; i < inventory.container.size; i++) {
    const item = inventory.container.getItem(i);
    inventorySnapshot.set(i, item ? item.typeId : null);
  }
  playerInventorySnapshots.set(player, inventorySnapshot);
}
function hasInventoryChanged(player) {
  const inventory = player.getComponent("inventory").container;
  const previousSnapshot = playerInventorySnapshots.get(player);
  if (!previousSnapshot) {
    snapshotPlayerInventory(player);
    return true;
  }
  for (let i = 0; i < inventory.size; i++) {
    const currentItem = inventory.getItem(i);
    const currentItemTypeId = currentItem ? currentItem.typeId : null;
    if (previousSnapshot.get(i) !== currentItemTypeId) {
      snapshotPlayerInventory(player);
      return true;
    }
  }
  return false;
}
function updateHotbarAndBlockItems(player, inventory, data) {
  const currentHotbar = /* @__PURE__ */ new Map();
  data.blockItems = /* @__PURE__ */ new Map();
  for (let i = 0; i < 9; i++) {
    const invItem = inventory.container.getItem(i);
    const typeId = invItem ? invItem.typeId : null;
    currentHotbar.set(i, typeId);
    if (invItem && typeId) {
      try {
        const placeable = BlockTypes.get(typeId);
        if (placeable && !typeId.includes("shulker")) {
          data.blockItems.set(i, invItem);
        }
      } catch (error) {
        console.warn(`Error checking item type for ${typeId}: ${error}`);
      }
    }
  }
  data.cachedHotbar = currentHotbar;
  snapshotPlayerInventory(player);
}
function calculateNewBlockLocation(data) {
  let newBlockLocation = { ...data.clickedBlockLocation };
  switch (data.clickedBlockFace.toLowerCase()) {
    case "west":
      newBlockLocation.x--;
      break;
    case "east":
      newBlockLocation.x++;
      break;
    case "down":
      newBlockLocation.y--;
      break;
    case "up":
      newBlockLocation.y++;
      break;
    case "north":
      newBlockLocation.z--;
      break;
    case "south":
      newBlockLocation.z++;
      break;
    default:
      console.warn(`Unrecognized face: ${data.clickedBlockFace}`);
  }
  return newBlockLocation;
}
function updateInventoryAfterPlacement(player, inventory, selectedSlot, selectedBlock, data, oldId) {
  if (player.getGameMode() === "creative")
    return;
  const currentStack = selectedBlock.amount;
  if (currentStack > 1) {
    selectedBlock.amount = currentStack - 1;
    inventory.container.setItem(selectedSlot, selectedBlock);
  } else {
    let foundReplacement = false;
    for (let i = 9; i < inventory.container.size; i++) {
      const invItem = inventory.container.getItem(i);
      if (invItem && invItem.typeId === selectedBlock.typeId) {
        const transferAmount = invItem.amount;
        selectedBlock.amount = transferAmount;
        inventory.container.setItem(selectedSlot, selectedBlock);
        inventory.container.setItem(i, void 0);
        foundReplacement = true;
        break;
      }
    }
    if (!foundReplacement) {
      inventory.container.setItem(selectedSlot, void 0);
      data.blockItems.delete(selectedSlot);
    }
  }
  if (oldId != "minecraft:air" && oldId != false) {
    player.runCommand(`gamerule sendcommandfeedback false`);
    player.runCommand(`give @s ${oldId} 1`);
    player.runCommand(`gamerule sendcommandfeedback true`);
    updateHotbarAndBlockItems(player, inventory, data);
  }
  snapshotPlayerInventory(player);
}
processQueue();
export {
  cooldownMap,
  twoTall
};
