import { world, system, ItemStack, EquipmentSlot, EntityComponentTypes, BlockPermutation } from "@minecraft/server";
import { guiTextureSelect, guiVariantSelect, guiRotationSelect, openToolBox, guiConnectDirection } from "./gui/index.js";
import * as db from "./database/blocks.js";
import {
  placeFenceComponent
} from "./connected/connected.js";
import {
  breakFenceComponent
} from "./connected/break.js";
import {
  placeLanternComponent,
  breakLanternComponent,
  toggleLanternComponent
} from "./connected/lantern.js";
import {
  breakSunshade,
  connectSunshade
} from "./connected/horizontal.js";
import "./seat.js";
import "./crates.js";
import { placeConnected } from "./connected/pillars.js";
import "./connected/pillars.js";
import { ConnectedBlockManager } from "./connected/pipes.js";
import "./connected/pipes.js";
import "./connected/girder.js";
import "./stairs.js";
import "./block_randomizer.js";
import "./exchanger.js";
import "./claw.js";
import { loadPlayerData } from "./exchanger.js";
import { replaceBlocks } from "./replaceBlocks.js";
const customComponents = {
  "maca_probuilder:place_fence": placeFenceComponent,
  "maca_probuilder:break_fence": breakFenceComponent,
  "maca_probuilder:place_lantern": placeLanternComponent,
  "maca_probuilder:break_lantern": breakLanternComponent,
  "maca_probuilder:toggle_lantern": toggleLanternComponent,
  "maca_probuilder:break_sunshade": breakSunshade,
  "maca_probuilder:place_sunshade": connectSunshade,
  "maca_probuilder:replaceBlock": replaceBlocks
};
world.beforeEvents.worldInitialize.subscribe(({ blockComponentRegistry }) => {
  for (const [componentName, componentImplementation] of Object.entries(customComponents)) {
    blockComponentRegistry.registerCustomComponent(componentName, componentImplementation);
  }
  loadParticleBlocks();
  loadPlayerData();
});
world.afterEvents.playerJoin.subscribe((e) => {
  system.runTimeout(() => {
    for (const player of world.getAllPlayers()) {
      if (player.id === e.playerId) {
        if (player.hasTag("maca_pb:highlight_active")) {
          player.removeTag("maca_pb:highlight_active");
          const entities = player.dimension.getEntities({
            location: player.location,
            maxDistance: 256,
            type: "maca_probuilder:highlight_entity"
          });
          for (const ent of entities) {
            ent.triggerEvent("despawn");
          }
        }
      }
    }
  }, 100);
});
world.beforeEvents.itemUseOn.subscribe((data) => {
  const { block, source, itemStack } = data;
  if (itemStack.typeId.includes("maca_probuilder:painter")) {
    return paintTool(block, source, itemStack);
  }
  if (itemStack.typeId.includes("maca_probuilder:copy")) {
    return copyTool(block, source, itemStack);
  }
  if (itemStack.typeId.includes("maca_probuilder:variant")) {
    if (block.hasTag("maca_probuilder:is_connected_vertical")) {
      return system.run(() => {
        placeConnected(block.dimension, block, true);
      });
    }
    if (block.hasTag("maca_probuilder:is_connected_pipe")) {
      const manager = new ConnectedBlockManager(block, block.typeId, "placed", true);
      return system.run(() => {
        manager.updateBlock();
      });
    }
    return variantTool(block, source, itemStack);
  }
  if (itemStack.typeId.includes("maca_probuilder:rotate")) {
    data.cancel = true;
    return rotateTool(block, source, itemStack);
  }
  if (itemStack.typeId.includes("maca_probuilder:")) {
    source.setDynamicProperty("maca_probuilder:stored_lore", itemStack.getLore()[0]);
    return;
  }
  if (!block.typeId.includes("maca_probuilder:"))
    return;
  if (source.hasTag("maca_probuilder:editormode")) {
    data.cancel = true;
    return editorModeReplaceTexture(block, source, itemStack);
  }
  if (block.typeId.includes("maca_probuilder:lantern") && itemStack.typeId.includes("minecraft:flint_and_steel"))
    return toggleLightBlock(data);
});
world.afterEvents.itemUse.subscribe((data) => {
  const { itemStack, source } = data;
  if (!itemStack.typeId.includes("maca_probuilder:"))
    return;
  if (source.isSneaking) {
    if (itemStack.typeId.includes("maca_probuilder:editor_"))
      return openToolBox(source);
    if (itemStack.typeId == "maca_probuilder:painter") {
      return openToolBox(source);
    }
    if (itemStack.typeId == "maca_probuilder:copy") {
      return openToolBox(source);
    }
    if (itemStack.typeId == "maca_probuilder:variant") {
      return openToolBox(source);
    }
    if (itemStack.typeId == "maca_probuilder:rotate") {
      return openToolBox(source);
    }
  }
  if (itemStack.typeId.includes("maca_probuilder:editor_"))
    return toggleEditorMode(data);
});
world.afterEvents.entityHitBlock.subscribe((data) => {
  const player = data.damagingEntity;
  const block = data.hitBlock;
  if (block.typeId === "maca_probuilder:crate_items")
    return;
  if (player.typeId != "minecraft:player")
    return;
  const equippableComponent = player.getComponent(EntityComponentTypes.Equippable);
  const itemStack = equippableComponent.getEquipment(EquipmentSlot.Mainhand);
  if (itemStack == void 0)
    return;
  if (!block.typeId.includes("maca_probuilder:") && !itemStack?.typeId.includes("maca_probuilder:rotate"))
    return;
  if (itemStack.typeId.includes("maca_probuilder:painter")) {
    return paintToolMenu(data);
  }
  if (itemStack.typeId.includes("maca_probuilder:copy")) {
    return copyToolMenu(data);
  }
  if (itemStack.typeId.includes("maca_probuilder:variant")) {
    return variantToolMenu(data);
  }
  if (itemStack.typeId.includes("maca_probuilder:rotate")) {
    return rotateToolMenu(data);
  }
});
world.afterEvents.playerPlaceBlock.subscribe((data) => {
  const block = data.block;
  const player = data.player;
  if (!block.typeId.includes("maca_probuilder:"))
    return;
  if (block.permutation.getState("maca_probuilder:axis_rotation") != void 0) {
    const rot = player.getRotation().y;
    if (rot >= 45 && rot < 125 || rot >= -125 && rot < -45)
      block.setPermutation(block.permutation.withState("maca_probuilder:axis_rotation", "z"));
  }
  const equipment = player.getComponent(EntityComponentTypes.Equippable);
  const itemStack = equipment.getEquipment(EquipmentSlot.Mainhand);
  if (itemStack && itemStack != void 0) {
    var storedLore = itemStack.getLore()[0];
  } else {
    storedLore = player.getDynamicProperty("maca_probuilder:stored_lore");
  }
  if (player.isSneaking) {
    const validTextures = getBlockTextures(block).map((x) => x.name);
    guiTextureSelect(player, block, validTextures, "", validTextures.findIndex((x) => x === storedLore));
  }
  if (storedLore != void 0)
    setBlock(player, block, storedLore, false);
});
world.afterEvents.playerSpawn.subscribe((e) => {
  const { player, initialSpawn } = e;
  player?.setDynamicProperty("maca_probuilder:player_communication", false);
  if (player.hasTag("maca:highlight_warning")) {
    player.removeTag("maca:highlight_warning");
  }
  ;
  if (!player?.getDynamicProperty("maca_probuilder:update1") && player?.getDynamicProperty("maca_probuilder:init")) {
    const manager = world.structureManager;
    const structure = manager.get("maca_pb:probuilder.addon_book");
    if (structure == void 0)
      return;
    manager.place(structure, player?.dimension, player?.location);
    player.onScreenDisplay.setTitle("\xA7bProbuilder Updated!", {
      subtitle: `Check out the new builders tools!!`,
      fadeInDuration: 2,
      fadeOutDuration: 2,
      stayDuration: 20 * 2
    });
    player?.setDynamicProperty("maca_probuilder:update1", true);
  }
  if (!initialSpawn)
    return;
  if (!player?.getDynamicProperty("maca_probuilder:init")) {
    const manager = world.structureManager;
    const structure = manager.get("maca_pb:probuilder.addon_book");
    if (structure == void 0)
      return;
    manager.place(structure, player?.dimension, player?.location);
    player.onScreenDisplay.setTitle("\xA7bWelcome to the\nProbuilder Addon!", {
      subtitle: `Check out your guidebook for details!`,
      fadeInDuration: 2,
      fadeOutDuration: 2,
      stayDuration: 20 * 2
    });
    player?.setDynamicProperty("maca_probuilder:update1", true);
    player?.setDynamicProperty("maca_probuilder:init", true);
  }
});
function editorModeReplaceTexture(block, source, itemStack) {
  var itemData = 0;
  if (db.extraItemData.find((x) => x.item === itemStack.typeId)) {
    for (const b of db.extraItemData) {
      if (itemStack.matches(b.item, b.states)) {
        itemData = b.itemData;
      }
    }
  }
  system.run(() => {
    setBlock(source, block, `${itemStack.typeId}:${itemData}`);
  });
}
function toggleLightBlock(data) {
  data.cancel = true;
  const { block } = data;
  if (block.permutation.getState("maca:is_lit")) {
    world.sendMessage("Light off light");
    system.run(() => {
      block.setPermutation(block.permutation.withState("maca:is_lit", false));
    });
  } else {
    world.sendMessage("Light on light");
    system.run(() => {
      block.setPermutation(block.permutation.withState("maca:is_lit", true));
    });
  }
}
function toggleEditorMode(data) {
  const { itemStack } = data;
  const player = data.source;
  const equippableComponent = player.getComponent(EntityComponentTypes.Equippable);
  if (itemStack.typeId.includes("maca_probuilder:editor_on")) {
    const editor = new ItemStack("maca_probuilder:editor_off");
    equippableComponent.setEquipment(EquipmentSlot.Mainhand, editor);
    sendPlayerCommunication(player, "tool.editor_off", "disable_editor");
    player.removeTag("maca_probuilder:editormode");
    return;
  } else {
    const editor = new ItemStack("maca_probuilder:editor_on");
    equippableComponent.setEquipment(EquipmentSlot.Mainhand, editor);
    sendPlayerCommunication(player, "tool.editor_on", "enable_editor");
    player.addTag("maca_probuilder:editormode");
    return;
  }
}
function paintTool(block, source, itemStack) {
  if (source.isSneaking) {
    return;
  } else {
    const lore = itemStack.getLore()[0];
    system.run(
      () => {
        if (lore === void 0 || lore === "") {
          sendPlayerCommunication(source, "tool.wrong_block", "failed_init_texture");
          return;
        }
        setBlock(source, block, lore);
      }
    );
    return;
  }
}
function copyTool(block, source, itemStack) {
  const lore = itemStack.getLore();
  if (source.isSneaking) {
    return;
  } else {
    system.run(() => {
      setBlock(source, block, lore[0]);
    });
  }
}
function variantTool(block, source, itemStack) {
  if (source.isSneaking) {
    return;
  }
  const blockId = block.typeId.replace("maca_probuilder:", "");
  const blockGroup = db.blocks.find((x) => x.id == blockId)?.group;
  if (!blockGroup) {
    if (blockId === "pipe" || blockId === "pillar") {
      system.run(() => {
        source.onScreenDisplay.setActionBar("Connecting to all blocks around");
      });
      return;
    }
    system.run(() => {
      sendPlayerCommunication(source, "tool.wrong_block", "no_variants");
    });
    return;
  }
  const blockVariants = db.blocks.filter((x) => x.group == blockGroup);
  const blockIndex = blockVariants.findIndex((x) => x.id == blockId);
  const newBlockId = `maca_probuilder:${blockVariants[(blockIndex + 1) % blockVariants.length].id}`;
  const blockStates = block.permutation.getAllStates();
  var newBlockStates = BlockPermutation.resolve(newBlockId);
  for (const state in blockStates) {
    if (newBlockStates.getState(state) == void 0)
      continue;
    newBlockStates = newBlockStates.withState(state, blockStates[state]);
  }
  system.run(() => {
    sendPlayerCommunication(source, "tool.variant", "set_variant", blockVariants[(blockIndex + 1) % blockVariants.length].name);
    block.setPermutation(newBlockStates);
  });
  return;
}
function rotateTool(block, source, itemStack) {
  if (source.isSneaking) {
    return;
  }
  const validPerms = [
    { id: "maca_probuilder:axis_rotation", states: ["x", "z"] },
    { id: "minecraft:facing_direction", states: ["east", "north", "west", "south", "up", "down"] },
    { id: "minecraft:cardinal_direction", states: ["east", "north", "west", "south"] },
    { id: "pillar_axis", states: ["x", "y", "z"] },
    { id: "facing_direction", states: [0, 1, 2, 3, 4, 5] },
    { id: "weirdo_direction", states: [0, 1, 2, 3] },
    { id: "direction", states: [0, 1, 2, 3] }
  ];
  let state = { id: "", states: [""] };
  for (const perm of validPerms) {
    var blockStateValue = block.permutation.getState(perm.id);
    if (blockStateValue != void 0) {
      state = perm;
      break;
    }
  }
  if (blockStateValue === void 0) {
    system.run(() => {
      sendPlayerCommunication(source, "tool.wrong_block", "no_rotations");
    });
    return;
  }
  const validStateValues = state.states;
  const blockIndex = validStateValues.findIndex((x) => x === blockStateValue);
  const newBlockState = validStateValues[(blockIndex + 1) % validStateValues.length];
  system.run(() => {
    const integer = state.id === "facing_direction" || state.id === "direction" || state.id === "weirdo_direction";
    block.setPermutation(block.permutation.withState(state.id, newBlockState));
    sendPlayerCommunication(source, "tool.rotate", "set_rotate", integer ? `State: ${newBlockState}` : `${newBlockState.charAt(0).toUpperCase()}${newBlockState.substring(1)}`);
  });
  return;
}
function paintToolMenu(data) {
  const block = data.hitBlock;
  const source = data.damagingEntity;
  const validTextures = getBlockTextures(block).map((x) => x.name);
  const index = (block.permutation.getState("maca_probuilder:texture_bit_0") ?? -1) + 16 * (block.permutation.getState("maca_probuilder:texture_bit_1") ?? 0);
  if (index === void 0 || index === -1) {
    sendPlayerCommunication(source, "tool.wrong_block", "no_textures");
    return;
  }
  guiTextureSelect(source, block, validTextures, "", index);
  return;
}
function copyToolMenu(data) {
  const block = data.hitBlock;
  const source = data.damagingEntity;
  const equippableComponent = source.getComponent(EntityComponentTypes.Equippable);
  const itemStack = equippableComponent.getEquipment(EquipmentSlot.Mainhand);
  const perm = block.permutation;
  const index = (perm.getState("maca_probuilder:texture_bit_0") ?? -1) + 16 * (perm.getState("maca_probuilder:texture_bit_1") ?? 0);
  if (index === void 0 || index === -1 || itemStack == void 0) {
    sendPlayerCommunication(source, "tool.wrong_block", "failed_copy_texture");
    return;
  }
  const blockTexture = getBlockTextures(block)[index].name;
  sendPlayerCommunication(source, "tool.paste", "copy_texture", blockTexture);
  itemStack.setLore([`${blockTexture}`]);
  equippableComponent.setEquipment(EquipmentSlot.Mainhand, itemStack);
}
function variantToolMenu(data) {
  const block = data.hitBlock;
  const source = data.damagingEntity;
  const blockId = block.typeId.replace("maca_probuilder:", "");
  const blockGroup = db.blocks.find((x) => x.id == blockId)?.group;
  let states = [];
  switch (blockId) {
    case "pipe":
      states = [
        { name: "up", value: block.permutation.getState("maca_probuilder:connect_up") == true },
        { name: "down", value: block.permutation.getState("maca_probuilder:connect_down") == true },
        { name: "north", value: block.permutation.getState("maca_probuilder:connect_north") == true },
        { name: "east", value: block.permutation.getState("maca_probuilder:connect_east") == true },
        { name: "south", value: block.permutation.getState("maca_probuilder:connect_south") == true },
        { name: "west", value: block.permutation.getState("maca_probuilder:connect_west") == true }
      ];
      break;
    case "pillar":
      states = [
        { name: "up", value: block.permutation.getState("maca_probuilder:connect_up") == 1 },
        { name: "down", value: block.permutation.getState("maca_probuilder:connect_down") == 1 }
      ];
      break;
    case "girder":
      states = [
        { name: "north", value: block.permutation.getState("maca_probuilder:connect_north") == true },
        { name: "east", value: block.permutation.getState("maca_probuilder:connect_east") == true },
        { name: "south", value: block.permutation.getState("maca_probuilder:connect_south") == true },
        { name: "west", value: block.permutation.getState("maca_probuilder:connect_west") == true }
      ];
      break;
  }
  if (states.length != 0) {
    guiConnectDirection(source, block, states);
  }
  if (!blockGroup) {
    sendPlayerCommunication(source, "tool.wrong_block", "no_variants");
    return;
  }
  const blockVariants = db.blocks.filter((x) => x.group == blockGroup);
  const blockIndex = blockVariants.findIndex((x) => x.id == blockId);
  guiVariantSelect(source, block, blockVariants.map((x) => x.name), "", blockIndex);
}
const particleBlocks = /* @__PURE__ */ new Set();
function stateManager(block) {
  const loc = block.location;
  const blockLocationString = `${loc.x},${loc.y},${loc.z}`;
  if (particleBlocks.has(blockLocationString)) {
    particleBlocks.delete(blockLocationString);
  } else {
    particleBlocks.add(blockLocationString);
  }
  saveParticleBlocks();
}
function saveParticleBlocks() {
  world.setDynamicProperty("ParticleBlocks", JSON.stringify([...particleBlocks]));
  loadParticleBlocks();
}
function loadParticleBlocks() {
  const ParticleData = world.getDynamicProperty("ParticleBlocks");
  if (ParticleData) {
    try {
      const parsedData = JSON.parse(ParticleData);
      particleBlocks.clear();
      for (const key of parsedData) {
        particleBlocks.add(key);
      }
    } catch (error) {
      console.error(`Error parsing ParticleBlocks data: ${error}`);
    }
  }
}
function rotateToolMenu(data) {
  const block = data.hitBlock;
  const source = data.damagingEntity;
  const validPerms = [
    { id: "maca_probuilder:axis_rotation", states: ["x", "z"] },
    { id: "minecraft:facing_direction", states: ["east", "north", "west", "south", "up", "down"] },
    { id: "minecraft:cardinal_direction", states: ["east", "north", "west", "south"] },
    { id: "pillar_axis", states: ["x", "y", "z"] },
    { id: "facing_direction", states: [0, 1, 2, 3, 4, 5] },
    { id: "weirdo_direction", states: [0, 1, 2, 3] },
    { id: "direction", states: [0, 1, 2, 3] }
  ];
  let state = { id: "", states: [""] };
  for (const perm of validPerms) {
    var blockStateValue = block.permutation.getState(perm.id);
    if (blockStateValue != void 0) {
      state = perm;
      break;
    }
  }
  if (blockStateValue === void 0) {
    sendPlayerCommunication(source, "tool.wrong_block", "no_rotations");
    return;
  }
  const validStateValues = state.states;
  const blockIndex = validStateValues.findIndex((x) => x === blockStateValue);
  const integer = state.id === "facing_direction" || state.id === "direction" || state.id === "weirdo_direction";
  guiRotationSelect(source, block, validStateValues.map((x) => integer ? `${x}` : `${x.charAt(0).toUpperCase()}${x.substring(1)}`), "", blockIndex, state.id);
}
function setBlock(player, block, index, announce = true) {
  const textures = getBlockTextures(block);
  if (typeof index === "string") {
    index = textures.findIndex((x) => x.name === index || x.item === index);
  }
  if (index === void 0 || index === -1)
    return sendPlayerCommunication(player, "tool.wrong_block", "failed_set_texture");
  let newPermutation = block.permutation.withState("maca_probuilder:texture_bit_0", index % 16);
  if (textures.length > 16) {
    newPermutation = newPermutation.withState("maca_probuilder:texture_bit_1", Math.floor(index / 16));
  }
  if (announce)
    sendPlayerCommunication(player, "tool.paste", "set_texture", textures[index].name);
  block.setPermutation(newPermutation);
}
function getBlockTextures(block) {
  return db.tags.filter((x) => block.getTags().includes("maca_probuilder:" + x.id)).flatMap((x) => x.array);
}
function sendPlayerCommunication(player, soundEffect, actionbarLang, actionbarWith = "") {
  if (player.getDynamicProperty("maca_probuilder:player_communication"))
    return;
  player.onScreenDisplay.setActionBar({ rawtext: [{ translate: `actionbar.maca_probuilder.${actionbarLang}`, with: ["\n", actionbarWith] }] });
  player.playSound(`maca_probuilder.${soundEffect}`);
  player.setDynamicProperty("maca_probuilder:player_communication", true);
  system.run(() => {
    player.setDynamicProperty("maca_probuilder:player_communication", false);
  });
}
export {
  copyTool,
  editorModeReplaceTexture,
  getBlockTextures,
  paintTool,
  particleBlocks,
  rotateTool,
  sendPlayerCommunication,
  setBlock,
  stateManager,
  variantTool
};
