import { system, world, BlockVolume, ItemStack, BlockPermutation } from "@minecraft/server";
import { spawnDeathMothFromSmallEgg, spawnDeathMothFromLargeEgg, triggerEggsFromHiveBlock, runIntoSmallDeathMothEggs } from "../b1/death_moth";
import { randomTrueFalse } from "../../utilities/helpers";
import { ModalFormData } from "@minecraft/server-ui";

export const grimStoneChunkComponent = {
  onTick({ block }) {
    if (block.permutation.getState("hb_hr:placed_bit") == true) return;
    let randomVariant;
    switch (block.typeId) {
      case "hb_hr:grim_stone_chunks":
        randomVariant = Math.floor(Math.random() * 2);
        break;
      default:
        randomVariant = 0;
        break;
    }
    const baseStates = {
      "hb_hr:placed_bit": true,
      "hb_hr:variant": randomVariant,
      "hb_hr:rotation": Math.floor(Math.random() * 3),
    };
    if (!block || block.typeId != "hb_hr:grim_stone_chunks") return;
    const newPerm = BlockPermutation.resolve(block.typeId, baseStates);
    block.setPermutation(newPerm);
  },
  beforeOnPlayerPlace(e) {
    const { permutationToPlace, block } = e;
    if (block.permutation.getState("hb_hr:placed_bit") == true) return;
    let randomVariant;
    switch (permutationToPlace.type.id) {
      case "hb_hr:grim_stone_chunks":
        randomVariant = Math.floor(Math.random() * 2);
        break;
      default:
        randomVariant = 0;
        break;
    }
    const baseStates = {
      "hb_hr:placed_bit": true,
      "hb_hr:variant": randomVariant,
      "hb_hr:rotation": Math.floor(Math.random() * 3),
    };

    const newPerm = BlockPermutation.resolve(permutationToPlace.type.id, baseStates);

    e.permutationToPlace = newPerm;
  },
};

// const grimStoneChunkComponent = {
//   onTick({ block }) {
//     if (block.typeId != "hb_hr:grim_stone_chunks") return;
//     if (block.permutation.getState("hb_hr:placed_bit") == true) return;
//     const randomVariant = Math.floor(Math.random() * 3);
//     const baseStates = {
//       "hb_hr:placed_bit": true,
//       "hb_hr:variant": randomVariant,
//     };
//     const newPerm = BlockPermutation.resolve(block.typeId, baseStates);
//     block.setPermutation(newPerm);
//   },
// };
const deadBushComponent = {
  onTick({ block }) {
    // Get the center and origin of the block
    const center = block.center();
    const blockPos = block.location; // Assuming block.location returns the block's integer coordinates

    // Get players within a 1 block radius of the block center
    const entities = block.dimension.getEntities({ location: center, maxDistance: 1 });
    for (const entity of entities) {
      if (entity.typeId == "hb_hr:screamer") return;
      const pos = entity.location;
      // Check if the entity's position is within the block's 1×1×1 boundaries
      // Tolerance for the Y-coordinate (e.g., to account for rounding errors)
      const epsilon = 0.01;

      // Check if the entity is exactly standing on the block:
      // - X and Z must be within the block boundaries
      // - Y must be exactly (or within a small tolerance of) blockPos.y + 1
      const onBlock = pos.x >= blockPos.x && pos.x < blockPos.x + 1 && pos.z >= blockPos.z && pos.z < blockPos.z + 1 && Math.abs(pos.y - (blockPos.y + 1)) < epsilon;

      // Define an additional area (margin) for "nearness" – here 0.6 units
      const margin = 0.6;

      // Check if the entity is near the block (considering horizontal distance):
      // The block area is extended by the margin
      const nearBlock = pos.x >= blockPos.x - margin && pos.x < blockPos.x + 1 + margin && pos.z >= blockPos.z - margin && pos.z < blockPos.z + 1 + margin;

      // Example: If you need a combined check (e.g., "on or near the block"):
      if (onBlock || nearBlock) {
        entity.applyDamage(1);
        // world.sendMessage("dead bush damage tick");
      }
    }
  },
};

const hiveBlocksComponent = {
  onPlayerDestroy(e) {
    if (e.player.hasTag("hb_hr:testing")) return;
    const { block, player } = e;
    const destroyedBlock = e.destroyedBlockPermutation;
    switch (destroyedBlock.type.id) {
      case "hb_hr:hive":
      case "hb_hr:hive_carpet":
      case "hb_hr:hive_carpet_block":
        triggerEggsFromHiveBlock(block, 3);
        break;
      case "hb_hr:large_hive_egg":
        triggerEggsFromHiveBlock(block, 3);
        spawnDeathMothFromLargeEgg(block, 1, 4);
        break;
      case "hb_hr:small_hive_egg":
        triggerEggsFromHiveBlock(block, 3);
        spawnDeathMothFromSmallEgg(block);
        break;
      case "hb_hr:hive_vine":
        break;
    }
  },
  // onTick({ block }) {
  //   // Get the center and origin of the block
  //   switch (block.typeId) {
  //     case "hb_hr:hive_vine":
  //       if (system.currentTick % 20 == 0) {
  //         vineCheckBlockBelow(block);
  //         // vineCheckBlockRandomizer(block);
  //       }
  //       vineClimbMechanic(block);
  //     case "hb_hr:small_hive_egg":
  //     case "hb_hr:hive_vine":
  //       runIntoSmallDeathMothEggs(block);
  //       break;
  //   }
  // },
  onStepOn({ block, entity }) {
    if (entity.hasTag("hb_hr:testing")) return;
    // Get the center and origin of the block
    switch (block.typeId) {
      case "hb_hr:large_hive_egg":
        try {
          triggerEggsFromHiveBlock(block, 3);
          spawnDeathMothFromLargeEgg(block, 1, 4);
        } catch (error) {}
        break;
    }
  },
};

const customComponents = {
  "hb_hr:dead_bush": deadBushComponent,
  "hb_hr:hive_block": hiveBlocksComponent,
  "hb_hr:grim_stone_chunk": grimStoneChunkComponent,
};

export class blockHandlerB1 {
  static initialized = false;
  static playerBiomeMap = new Map(); // Speichert zuletzt erkannte Biome für jeden Spieler

  constructor() {
    this.initialize();
  }

  initialize() {
    if (!blockHandlerB1.initialized) {
      blockHandlerB1.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;

      breakVines(event.block);

      switch (block.typeId) {
        case "hb_hr:grim_stone_chunks":
          if (block.permutation.getState("hb_hr:placed_bit") == true) return;
          const randomVariant = Math.floor(Math.random() * 3);
          const baseStates = {
            "hb_hr:placed_bit": true,
            "hb_hr:variant": randomVariant,
          };
          const newPerm = BlockPermutation.resolve(block.typeId, baseStates);
          block.setPermutation(newPerm);
          break;
        case "hb_hr:hive_vine":
          if (player.getGameMode() == "creative") {
            // In creative mode, set the "has_eggs" state to a random boolean value.
            const newPermutation = BlockPermutation.resolve(block.typeId).withState("hb_hr:has_eggs", randomTrueFalse());
            block.setPermutation(newPermutation);
          }
          if (!block.above()) return;

          if (block.above().typeId == block.typeId) {
            // Set permutation for the block above: full_block is true and its egg state is preserved.
            const newPermutationAbove = BlockPermutation.resolve(block.typeId, {
              "hb_hr:full_block": true,
              "hb_hr:has_eggs": block.above().permutation.getState("hb_hr:has_eggs"),
            });
            block.above().setPermutation(newPermutationAbove);

            // Set permutation for the current block: full_block is false and its egg state is preserved.
            const newPermutation = BlockPermutation.resolve(block.typeId, {
              "hb_hr:full_block": false,
              "hb_hr:has_eggs": block.permutation.getState("hb_hr:has_eggs"),
            });
            block.setPermutation(newPermutation);
          }
          if (block.below().typeId == block.typeId && block.below().below().typeId != block.typeId) {
            // For the last vine block in a continuous column, set its permutation to have full_block false,
            // while preserving its egg state.
            const newPermutationBelow = BlockPermutation.resolve(block.typeId, {
              "hb_hr:full_block": false,
              "hb_hr:has_eggs": block.below().permutation.getState("hb_hr:has_eggs"),
            });
            block.below().setPermutation(newPermutationBelow);
          }
          if (block.below().typeId != block.typeId) {
            // If the block below is not of the same type, update the current block's permutation to have full_block false
            // and preserve its egg state.
            const newPermutationBelow = BlockPermutation.resolve(block.typeId, {
              "hb_hr:full_block": false,
              "hb_hr:has_eggs": block.permutation.getState("hb_hr:has_eggs"),
            });
            block.setPermutation(newPermutationBelow);
          }
          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;
      checkEggs(event.block);
      if (event.block.typeId == "minecraft:air" && event.block.above().typeId == "hb_hr:hive_vine") {
        // If the event block is air and the block above is a hive vine, update the above block's permutation.
        const newPermutationAbove = BlockPermutation.resolve("hb_hr:hive_vine", {
          "hb_hr:full_block": false,
          "hb_hr:has_eggs": event.block.above().permutation.getState("hb_hr:has_eggs"),
        });
        event.block.above().setPermutation(newPermutationAbove);
      }

      if (event.block.below().typeId == "hb_hr:hive_vine") {
        // Cast a ray downward from the event block to find the last vine block.
        const lastVineBlock = player.dimension.getBlockFromRay(
          event.block.location,
          { x: 0, y: -100, z: 0 },
          {
            includeTypes: ["hb_hr:hive_vine"],
            excludePermutations: [BlockPermutation.resolve("hb_hr:hive_vine", { "hb_hr:full_block": true, "hb_hr:has_eggs": false }), BlockPermutation.resolve("hb_hr:hive_vine", { "hb_hr:full_block": true, "hb_hr:has_eggs": true })],
          },
        );

        // Create a volume from the event block's location to the last vine block's location.
        const volume = new BlockVolume({ x: event.block.location.x, y: event.block.location.y, z: event.block.location.z }, { x: event.block.location.x, y: lastVineBlock.block.location.y, z: event.block.location.z });

        // Iterate over each block location in the volume and replace the block with air.
        const locations = volume.getBlockLocationIterator();
        for (const location of locations) {
          const vineBlock = player.dimension.getBlock(location);
          player.dimension.runCommand("/fill " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " air destroy");
        }
      }

      switch (block.type.id) {
        case "hb_hr:dead_bush":
          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:dead_bush");
                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:dead_grass":
          if (usedItem == undefined) {
            if (Math.random() > seedDropChance) {
              blockItem = new ItemStack("minecraft:stick");
            }
          }
          if (usedItem) {
            switch (usedItem.typeId) {
              case undefined:
                if (Math.random() > seedDropChance) blockItem = new ItemStack("minecraft:stick");
                break;
              case "minecraft:shears":
                blockItem = new ItemStack("hb_hr:dead_grass");
                break;

              default:
                if (Math.random() > seedDropChance) {
                  blockItem = new ItemStack("minecraft:stick");
                }
                break;
            }
          }
          if (blockItem != "empty") {
            world.getDimension(player.dimension.id).spawnItem(blockItem, event.block.location);
          }
          break;
        // all maze blocks
        case "hb_hr:chiseled_grim_stone_bricks":
        case "hb_hr:cracked_grim_stone_bricks":
        case "hb_hr:grim_stone_bricks_slab":
        case "hb_hr:grim_stone_bricks":
        case "hb_hr:infested_grim_stone_bricks":
        case "hb_hr:grim_stone_bricks_wall":
        case "hb_hr:grim_stone_bricks_roof":
        case "hb_hr:polished_grim_stone":
        // normal b1 stone blocks
        case "hb_hr:grim_stone":
        case "hb_hr:grim_stone_chunks":
          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")) {
            this.spawnItemFromBlock(player, event.block, block.type.id);
          }
          break;
        // b1 blight wood
        case "hb_hr:blight_roof":
          if (usedItem == undefined) {
            this.spawnItemFromBlock(player, event.block, block.type.id);
            return;
          }
          this.spawnItemFromBlock(player, event.block, block.type.id);
          break;
        case "hb_hr:soul_ore":
          if (usedItem == undefined) return;
          if (usedItem.getComponent("enchantable") != undefined) {
            const enchants = usedItem.getComponent("enchantable");
            if (enchants.getEnchantment("silk_touch") != undefined) {
              // blockItem = new ItemStack("hb_hr:soul_ore");
              // world.getDimension(player.dimension.id).spawnItem(blockItem, event.block.location);
              // world.sendMessage("spawn1");
              break;
              return;
            }
          }
          if (usedItem.hasTag("minecraft:is_pickaxe") || usedItem.typeId.includes("pickaxe")) {
            this.spawnItemFromBlock(player, event.block, "hb_hr:soul_piece");
            // world.sendMessage("spawn2");
          }
          break;
        case "hb_hr:dirty_dead_roots":
          this.spawnItemFromBlock(player, event.block, "hb_hr:dirty_dead_roots");
          break;
        case "hb_hr:rotten_soil":
        case "hb_hr:dried_dirt":
          this.spawnItemFromBlock(player, event.block, block.type.id);
          break;
        case "hb_hr:hive":
        case "hb_hr:hive_carpet":
          if (usedItem == undefined) return;
          if (usedItem.getComponent("enchantable") != undefined) {
            const enchants = usedItem.getComponent("enchantable");
            if (enchants.getEnchantment("silk_touch") != undefined) {
              return;
              // blockItem = new ItemStack(block.typeId);
            }
          }
          break;
        case "hb_hr:hive_vine":
          if (usedItem == undefined) {
            break;
          }
          if (usedItem) {
            switch (usedItem.typeId) {
              case undefined:
                break;
              case "minecraft:shears":
                blockItem = new ItemStack("hb_hr:hive_vine");
                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;
        // ALREADYM INCLUDED IN THE TREE TEMPLATE
        // case "hb_hr:blight_leaves":
        //   let dropSelector = Math.random();
        //   if (usedItem == undefined) {
        //     if (dropSelector < 0.02) {
        //       blockItem = new ItemStack("minecraft:stick");
        //     } else if (dropSelector < 0.07) {
        //       blockItem = new ItemStack("hb_hr:blight_sapling");
        //     }
        //     world.sendMessage("spawn");
        //     if (blockItem != "empty") world.getDimension(player.dimension.id).spawnItem(blockItem, event.block.location);
        //     return;
        //   }
        //   if (usedItem.hasTag("minecraft:is_shears") || usedItem.typeId.includes("shears")) {
        //     blockItem = new ItemStack("hb_hr:blight_leaves");
        //   }
        //   if (usedItem.getComponent("enchantable") != undefined) {
        //     const enchants = usedItem.getComponent("enchantable");
        //     if (enchants.getEnchantment("silk_touch") != undefined) {

        //       blockItem = new ItemStack("hb_hr:blight_leaves");
        //     }
        //   }
        //   world.sendMessage("spawn");
        //   if (blockItem != "empty") world.getDimension(player.dimension.id).spawnItem(blockItem, event.block.location);
        //   break;
        default:
          break;
      }
    });
  }

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

export function vineCheckBlockBelow(block) {
  if (block.below().typeId == "minecraft:air" || block.below().typeId == "hb_hr:hive_carpet" || block.below().typeId == "minecraft:structure_void" || block.below().typeId == "hb_hr:small_hive_egg" || block.below().typeId == "hb_hr:large_hive_egg") {
    if (block.permutation.getState("hb_hr:full_block") == false) return;
    const newPermutationAbove = BlockPermutation.resolve(block.typeId, {
      "hb_hr:full_block": false,
      "hb_hr:has_eggs": block.permutation.getState("hb_hr:has_eggs"),
    });
    block.setPermutation(newPermutationAbove);
  }
}

export function vineCheckBlockRandomizer(block) {
  if (block.permutation.getState("hb_hr:full_block") == false) return;
  const newPermutationAbove = BlockPermutation.resolve(block.typeId, {
    "hb_hr:full_block": true,
    "hb_hr:has_eggs": randomTrueFalse(),
  });
  block.setPermutation(newPermutationAbove);
}
export function vineClimbMechanic(block) {
  const center = block.center();
  const blockPos = block.location; // Assuming block.location returns the block's integer coordinates

  // Get players within a 1 block radius of the block center
  const players = block.dimension.getEntities({ location: center, maxDistance: 0.85 });
  for (const player of players) {
    const pos = player.location;
    // Check if the player's position (assumed to be the feet) is inside the block.
    // This verifies that the player's coordinates fall within the block's 1×1×1 boundaries.
    // const insideBlock = pos.x >= blockPos.x && pos.x < blockPos.x + 1 && pos.z >= blockPos.z && pos.z < blockPos.z + 1 && pos.y >= blockPos.y && pos.y < blockPos.y + 1;

    // If the player is inside the block, perform the vine climb actions.
    // if (insideBlock) {
    // For hive vine blocks, check if the egg and full_block states are set.
    if (block.typeId == "hb_hr:hive_vine") {
      const playerVelocity = player.getVelocity();
      if (player.isJumping) {
        player.applyKnockback(0, 0, 0, 0.4);
      } else {
        if (playerVelocity.y < 0) {
          player.addEffect("slow_falling", 20, { amplifier: 0, showParticles: false });
        }
      }
    }
  }
}

export function breakVines(block) {
  if (block.typeId == "minecraft:air" && block.above().typeId == "hb_hr:hive_vine") {
    // If the event block is air and the block above is a hive vine, update the above block's permutation.
    const newPermutationAbove = BlockPermutation.resolve("hb_hr:hive_vine", {
      "hb_hr:full_block": false,
      "hb_hr:has_eggs": block.above().permutation.getState("hb_hr:has_eggs"),
    });
    block.above().setPermutation(newPermutationAbove);
  }

  if (block.below().typeId == "hb_hr:hive_vine") {
    // Cast a ray downward from the event block to find the last vine block.
    const lastVineBlock = block.dimension.getBlockFromRay(
      block.location,
      { x: 0, y: -100, z: 0 },
      {
        includeTypes: ["hb_hr:hive_vine"],
        excludePermutations: [BlockPermutation.resolve("hb_hr:hive_vine", { "hb_hr:full_block": true, "hb_hr:has_eggs": false }), BlockPermutation.resolve("hb_hr:hive_vine", { "hb_hr:full_block": true, "hb_hr:has_eggs": true })],
      },
    );

    // Create a volume from the event block's location to the last vine block's location.
    const volume = new BlockVolume({ x: block.location.x, y: block.location.y, z: block.location.z }, { x: block.location.x, y: lastVineBlock.block.location.y, z: block.location.z });

    // Iterate over each block location in the volume and replace the block with air.
    const locations = volume.getBlockLocationIterator();
    for (const location of locations) {
      const vineBlock = block.dimension.getBlock(location);
      block.dimension.runCommand("/fill " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " " + vineBlock.location.x + " " + vineBlock.location.y + " " + vineBlock.location.z + " air destroy");
    }
  }
}

export function checkEggs(block) {
  const directions = [
    { x: 1, y: 0, z: 0 }, // rechts
    { x: -1, y: 0, z: 0 }, // links
    { x: 0, y: 1, z: 0 }, // oben
    { x: 0, y: -1, z: 0 }, // unten
    { x: 0, y: 0, z: 1 }, // vorne
    { x: 0, y: 0, z: -1 }, // hinten
  ];

  let i = 0;
  for (const dir of directions) {
    const neighborLocation = {
      x: block.location.x + dir.x,
      y: block.location.y + dir.y,
      z: block.location.z + dir.z,
    };

    const testBlock = block.dimension.getBlock(neighborLocation);
    if (!testBlock) continue;
    const blockType = testBlock.typeId;
    if (!blockType.includes("hive_egg") && !blockType.includes("hb_hr")) continue;
    // world.sendMessage(blockType);
    // world.sendMessage("sdaasda");
    switch (blockType) {
      case "hb_hr:large_hive_egg":
        spawnDeathMothFromLargeEgg(block, 1, 4);
        block.dimension.runCommand("/fill " + testBlock.location.x + " " + testBlock.location.y + " " + testBlock.location.z + " " + testBlock.location.x + " " + testBlock.location.y + " " + testBlock.location.z + " air destroy");
        break;
      case "hb_hr:small_hive_egg":
        spawnDeathMothFromSmallEgg(block);
        block.dimension.runCommand("/fill " + testBlock.location.x + " " + testBlock.location.y + " " + testBlock.location.z + " " + testBlock.location.x + " " + testBlock.location.y + " " + testBlock.location.z + " air destroy");
        break;
    }
  }
}
