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

const cursedBushComponent = {
  onTick({ block }) {
    const center = block.center();
    const blockPos = block.location; // Assuming block.location returns the block's integer coordinates

    // const testBlockVolume = new BlockVolume({ x: blockPos.x, y: blockPos.y, z: blockPos.z }, { x: blockPos.x, y: blockPos.y - 1, z: blockPos.z });

    // Get players within a 1 block radius of the block center
    const players = block.dimension.getEntities({ location: center, type: "minecraft:player", excludeTags: ["hb_hr:testing"], maxDistance: 1 });
    for (const player of players) {
      const pos = player.location;
      // Define player's bounding box assuming a height of 2 blocks.
      const playerBottom = pos.y;
      const playerTop = pos.y; // Player's height is 2 blocks
      const epsilon = 0.01; // Tolerance for vertical checks

      // Check if the player's bounding box intersects with the top surface of the block:
      // - X and Z must be within the block boundaries.
      // - The block's top (blockPos.y + 1) must lie between the player's bottom and top.
      const onBlock = pos.x >= blockPos.x && pos.x < blockPos.x + 1 && pos.z >= blockPos.z && pos.z < blockPos.z + 1 && playerBottom - epsilon <= blockPos.y + 1 && playerTop + epsilon >= blockPos.y + 1;

      // Define an additional horizontal margin for "nearness" – here 0.6 units.
      const margin = 0.2;
      const nearBlock = pos.x >= blockPos.x - margin && pos.x < blockPos.x + 1 + margin && pos.z >= blockPos.z - margin && pos.z < blockPos.z + 1 + margin;

      // If the player is on, near, or under the block, trigger the appropriate actions.
      if (onBlock || nearBlock) {
        if (block.typeId == "hb_hr:cursed_bush") {
          try {
            if (system.currentTick % 5 == 0) player.dimension.spawnParticle("hb_hr:cursed_bush_walk_thru", block.location);
          } catch (error) {}
          player.addEffect("slowness", 20, { amplifier: 3 });
        }
      }
    }
  },
};
const grimStoneChunkComponent = {
  onTick({ block }) {
    const center = block.center();
    const blockPos = block.location; // Assuming block.location returns the block's integer coordinates

    // const testBlockVolume = new BlockVolume({ x: blockPos.x, y: blockPos.y, z: blockPos.z }, { x: blockPos.x, y: blockPos.y - 1, z: blockPos.z });

    // Get players within a 1 block radius of the block center
    const players = block.dimension.getEntities({ location: center, type: "minecraft:player", excludeTags: ["hb_hr:testing"], maxDistance: 1 });
    for (const player of players) {
      const pos = player.location;
      // Define player's bounding box assuming a height of 2 blocks.
      const playerBottom = pos.y;
      const playerTop = pos.y; // Player's height is 2 blocks
      const epsilon = 0.01; // Tolerance for vertical checks

      // Check if the player's bounding box intersects with the top surface of the block:
      // - X and Z must be within the block boundaries.
      // - The block's top (blockPos.y + 1) must lie between the player's bottom and top.
      const onBlock = pos.x >= blockPos.x && pos.x < blockPos.x + 1 && pos.z >= blockPos.z && pos.z < blockPos.z + 1 && playerBottom - epsilon <= blockPos.y + 1 && playerTop + epsilon >= blockPos.y + 1;

      // Define an additional horizontal margin for "nearness" – here 0.6 units.
      const margin = 0.2;
      const nearBlock = pos.x >= blockPos.x - margin && pos.x < blockPos.x + 1 + margin && pos.z >= blockPos.z - margin && pos.z < blockPos.z + 1 + margin;

      // If the player is on, near, or under the block, trigger the appropriate actions.
      if (onBlock || nearBlock) {
        if (block.typeId == "hb_hr:cursed_bush") {
          try {
            if (system.currentTick % 5 == 0) player.dimension.spawnParticle("hb_hr:cursed_bush_walk_thru", block.location);
          } catch (error) {}
          player.addEffect("slowness", 20, { amplifier: 3 });
        }
      }
    }
  },
};

const customComponents = {
  "hb_hr:cursed_bush": cursedBushComponent,
};

export class blockHandlerB2 {
  static initialized = false;
  static playerBiomeMap = new Map();

  constructor() {
    this.initialize();
  }

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

  processSubscriptions() {
    // Use this world initialization event to register all custom components
    world.beforeEvents.worldInitialize.subscribe(({ blockComponentRegistry }) => {
      for (const [componentName, componentImplementation] of Object.entries(customComponents)) {
        blockComponentRegistry.registerCustomComponent(componentName, componentImplementation);
      }
    });
    world.afterEvents.playerPlaceBlock.subscribe((event) => {
      const block = event.block;
      const player = event.player;

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

      switch (block.type.id) {
        case "hb_hr:fake_bone_block":
          if (usedItem == undefined) return;
          if (usedItem.getComponent("enchantable") != undefined) {
            const enchants = usedItem.getComponent("enchantable");
            if (enchants.getEnchantment("silk_touch") != undefined) {
              return;
            }
          }
          if (usedItem.hasTag("minecraft:is_pickaxe") || usedItem.typeId.includes("pickaxe")) {
            blockItem = new ItemStack("minecraft:bone_block");
          }
          if (blockItem != "empty") {
            world.getDimension(player.dimension.id).spawnItem(blockItem, event.block.location);
          }
          break;
        case "hb_hr:cursed_short_grass":
          if (usedItem == undefined) {
            if (Math.random() > seedDropChance) {
              blockItem = new ItemStack("minecraft:wheat_seeds");
            }
          }
          if (usedItem) {
            switch (usedItem.typeId) {
              case undefined:
                if (Math.random() > seedDropChance) blockItem = new ItemStack("minecraft:wheat_seeds");
                break;
              case "minecraft:shears":
                blockItem = new ItemStack("hb_hr:cursed_short_grass");
                break;

              default:
                if (Math.random() > seedDropChance) {
                  blockItem = new ItemStack("minecraft:wheat_seeds");
                }
                break;
            }
          }
          if (blockItem != "empty") {
            world.getDimension(player.dimension.id).spawnItem(blockItem, event.block.location);
          }
          break;

        case "hb_hr:cursed_grass_block":
        case "hb_hr:dried_cursed_grass_block":
          if (usedItem == undefined) {
            blockItem = new ItemStack("minecraft:dirt");
          }
          if (usedItem) {
            switch (usedItem.typeId) {
              case undefined:
                blockItem = new ItemStack("minecraft:dirt");
                break;

              default:
                blockItem = new ItemStack("minecraft:dirt");
                break;
            }
            if (usedItem.getComponent("enchantable") != undefined) {
              const enchants = usedItem.getComponent("enchantable");
              if (enchants.getEnchantment("silk_touch") != undefined) {
                return;
              }
            }
          }
          if (blockItem != "empty") {
            world.getDimension(player.dimension.id).spawnItem(blockItem, event.block.location);
          }
          break;
        case "hb_hr:cursed_vine":
          if (usedItem == undefined) {
            if (Math.random() < 0.3) {
              blockItem = new ItemStack("hb_hr:cursed_sapling");
            }
            break;
          }
          if (usedItem) {
            switch (usedItem.typeId) {
              case undefined:
                if (Math.random() < 0.3) {
                  blockItem = new ItemStack("hb_hr:cursed_sapling");
                }
                break;
              case "minecraft:shears":
                blockItem = new ItemStack("hb_hr:cursed_vine");
                break;
              default:
                if (Math.random() < 0.05) {
                  blockItem = new ItemStack("hb_hr:cursed_sapling");
                }
            }
            if (usedItem.getComponent("enchantable") != undefined) {
              const enchants = usedItem.getComponent("enchantable");
              if (enchants.getEnchantment("silk_touch") != undefined) {
                return;
              }
            }
          }
          if (blockItem != "empty") {
            world.getDimension(player.dimension.id).spawnItem(blockItem, event.block.location);
          }
          break;

        default:
          break;
      }
    });
  }

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

export function placeFarmland() {
  const farmlandBlocks = ["hb_hr:cursed_grass_block", "hb_hr:dried_cursed_grass_block"];

  world.beforeEvents.itemUseOn.subscribe((event) => {
    const block = event.block;
    const player = event.source;
    const itemStack = event.itemStack;
    if (player.typeId !== "minecraft:player") return;

    if (!(itemStack.typeId.includes("minecraft:") && itemStack.typeId.includes("hoe"))) return;
    if (!itemStack) return;

    system.run(() => {
      const testBlock = world.getDimension(player.dimension.id).getBlock(block.location);
      if (farmlandBlocks.includes(testBlock.typeId)) {
        world
          .getDimension(player.dimension.id)
          .getBlock({ x: testBlock.location.x + 0.5, y: testBlock.location.y, z: testBlock.location.z + 0.5 })
          .setType("minecraft:farmland");
      }
    });
  });
}
