import { world, system, BlockPermutation } from "@minecraft/server";
import {
  forestryLogsPlusVanilla,
  forestryLeavesPlusVanilla,
  forestryLogsPlusVanillaIndexCount,
  forestryLogsPlusVanillaArray,
} from "../globals";

// Function to get the matched forestry log or wood ID
function getMatchedForestryLogOrWoodId(brokenblock) {
  try {
    for (const logType of forestryLogsPlusVanilla) {
      if (brokenblock.matches(logType) || brokenblock.matches(logType.replace("log", "wood"))) {
        return logType;
      }
    }
    return null;
  } catch (e) {
    console.warn(`Error in getMatchedForestryLogOrWoodId: ${e}`);
  }
}

// Function to get the matched forestry leaf ID
function getMatchedForestryLeafId(brokenblock) {
  try {
    for (const leafType of forestryLeavesPlusVanilla) {
      if (brokenblock.matches(leafType)) {
        return leafType;
      }
    }
    return null;
  } catch (e) {
    console.warn(`Error in getMatchedForestryLeafId: ${e}`);
  }
}

// Function to get the corresponding leaf type from a log or wood type
function getCorrespondingLeafType(blockType) {
  try {
    // Rainbow logs/woods
    if (blockType === "float_fc:rainbow_log" || blockType === "float_fc:rainbow_wood") {
      return [
        "float_fc:rainbow_leaves_blue",
        "float_fc:rainbow_leaves_cyan",
        "float_fc:rainbow_leaves_green",
        "float_fc:rainbow_leaves_orange",
        "float_fc:rainbow_leaves_pink",
        "float_fc:rainbow_leaves_purple",
        "float_fc:rainbow_leaves_red",
        "float_fc:rainbow_leaves_yellow",
      ];
    }
    if (
      blockType === "float_fc:bone_wood" ||
      blockType === "float_fc:bone_log" ||
      blockType === "float_fc:stripped_bone_wood" ||
      blockType === "float_fc:stripped_bone_log"
    ) {
      return [
        "float_fc:bone_leaves_flame",
        "float_fc:bone_leaves",
        "float_fc:stripped_bone_wood",
        "float_fc:stripped_bone_log",
        "float_fc:bone_wood",
        "float_fc:bone_log",
      ];
    }
    if (
      blockType === "minecraft:mangrove_roots" ||
      blockType === "minecraft:muddy_mangrove_roots" ||
      blockType === "minecraft:mangrove_log" ||
      blockType === "minecraft:stripped_mangrove_log" ||
      blockType === "minecraft:stripped_mangrove_wood"
    ) {
      return [
        "minecraft:mangrove_roots",
        "minecraft:muddy_mangrove_roots",
        "minecraft:mangrove_log",
        "minecraft:mangrove_leaves",
      ];
    }
    if (blockType === "float_fc:scorched_log" || blockType === "float_fc:scorched_wood") {
      return [
        "float_fc:scorched_leaves_flame",
        "float_fc:scorched_leaves",
        "float_fc:scorched_wood",
        "float_fc:stripped_scorched_wood",
      ];
    }

    // Giant mushrooms (vanilla)
    if (
      blockType === "minecraft:mushroom_stem" ||
      blockType === "minecraft:brown_mushroom_block" ||
      blockType === "minecraft:red_mushroom_block"
    ) {
      return ["minecraft:mushroom_stem", "minecraft:brown_mushroom_block", "minecraft:red_mushroom_block"];
    }

    // Crimson and Warped fungi trees
    if (blockType === "minecraft:crimson_stem" || blockType === "minecraft:warped_stem") {
      return [
        "minecraft:crimson_stem",
        "minecraft:warped_stem",
        "minecraft:crimson_wart_block",
        "minecraft:warped_wart_block",
        "minecraft:shroomlight", // Added shroomlight
      ];
    }

    // Stripped scorched logs
    if (
      blockType === "float_fc:stripped_scorched_log" ||
      blockType === "float_fc:stripped_scorched_wood" ||
      blockType.startsWith("float_fc:stripped_scorched")
    ) {
      return [blockType];
    }

    // Mushroom wood
    if (
      blockType === "float_fc:mushroom_wood" ||
      blockType === "float_fc:mushroom_log" ||
      blockType === "float_fc:stripped_mushroom_log" ||
      blockType === "float_fc:stripped_mushroom_wood"
    ) {
      return ["float_fc:mushroom_leaves", "float_fc:mushroom_leaves_inside"];
    }

    // Oak logs/wood should also destroy azalea leaves
    if (
      blockType === "minecraft:oak_log" ||
      blockType === "minecraft:oak_wood" ||
      blockType === "minecraft:stripped_oak_log" ||
      blockType === "minecraft:stripped_oak_wood"
    ) {
      return ["minecraft:oak_leaves", "minecraft:azalea_leaves_flowered", "minecraft:azalea_leaves"];
    }

    // Default behavior for logs and woods
    if (blockType.includes("log")) {
      return [blockType.replace("log", "leaves")];
    } else if (blockType.includes("wood")) {
      return [blockType.replace("wood", "leaves")];
    }

    return [blockType];
  } catch (e) {
    console.warn(`Error in getCorrespondingLeafType: ${e}`);
  }
}

// Function to check if a block is either a log or wood of the same tree type
function isMatchingLogOrWood(blockType, initialBlockType) {
  try {
    return (
      blockType === initialBlockType ||
      blockType === initialBlockType.replace("log", "wood") ||
      blockType === initialBlockType.replace("wood", "log")
    );
  } catch (e) {
    console.warn(`Error in isMatchingLogOrWood: ${e}`);
  }
}

// Function to group items within a radius to the initial location
function groupItemsAtInitialLocation(dimension, initialLocation, radius = 10) {
  try {
    const items = dimension.getEntities({
      type: "minecraft:item",
      location: initialLocation,
      maxDistance: radius,
    });

    if (items.length > 0) {
      items.forEach((item) => {
        item.teleport(initialLocation); // Teleport all items to the initial location
      });
    }
  } catch (e) {
    console.warn(`Error in groupItemsAtInitialLocation: ${e}`);
  }
}

let activeGroupingInterval = null;
let activeTreeChopping = false;
let destroyedBlockCount = 0; // Initialize counter for total destroyed blocks
let destroyedBlockTypeCounts = {}; // Initialize counter for each block type
let pendingBlocks = 0; // Counter to track active recursive calls

function startItemGrouping(dimension, initialLocation) {
  if (activeGroupingInterval) return; // Prevent multiple intervals
  activeGroupingInterval = system.runInterval(() => {
    if (activeTreeChopping) {
      groupItemsAtInitialLocation(dimension, initialLocation, 15);
    } else {
      stopItemGrouping(); // Stop grouping if no tree chopping is active
    }
  }, 20); // Run every 1 second (20 ticks)
}

function stopItemGrouping() {
  if (activeGroupingInterval) {
    system.clearRun(activeGroupingInterval);
    activeGroupingInterval = null;
  }
}

function decrementPendingBlocks(dimension, initialLocation) {
  pendingBlocks--;
  if (pendingBlocks <= 0) {
    system.runTimeout(() => {
      groupItemsAtInitialLocation(dimension, initialLocation, 15); // Run one final grouping
      stopItemGrouping(); // Stop grouping after the delay
    }, 40); // 2 seconds delay (40 ticks)
  }
}

export default function chainsawtree(
  player,
  blockOrPermutation,
  location,
  initialBlockType,
  indexCheck,
  firstLocation
) {
  try {
    if (indexCheck == undefined) {
      indexCheck = 0;
    }
    if (!firstLocation) {
      firstLocation = location; // Set the first block's location
      activeTreeChopping = true; // Mark tree chopping as active
      destroyedBlockCount = 0; // Reset total counter
      destroyedBlockTypeCounts = {}; // Reset type-specific counters
      pendingBlocks = 1; // Initialize pending blocks counter with the first block
      startItemGrouping(player.dimension, firstLocation); // Start grouping when the first block is destroyed
    }

    const blockPermutation = blockOrPermutation.permutation ? blockOrPermutation.permutation : blockOrPermutation;

    // Determine the initial block type if not already set
    if (!initialBlockType) {
      initialBlockType = getMatchedForestryLogOrWoodId(blockPermutation) || getMatchedForestryLeafId(blockPermutation);
    }

    // Check if blockPermutation matches the initial block type or its corresponding leaf types
    if (
      !initialBlockType ||
      (!isMatchingLogOrWood(blockPermutation.type.id, initialBlockType) &&
        !getCorrespondingLeafType(initialBlockType).includes(blockPermutation.type.id))
    ) {
      decrementPendingBlocks(player.dimension, firstLocation); // Decrement pending blocks if this block doesn't match
      return;
    }

    const dimension = player.dimension;
    let blockx = location.x;
    let blocky = location.y;
    let blockz = location.z;

    dimension.runCommand(`setblock ${blockx} ${blocky} ${blockz} air destroy`);
    destroyedBlockCount++; // Increment the total counter
    const blockType = blockPermutation.type.id;
    destroyedBlockTypeCounts[blockType] = (destroyedBlockTypeCounts[blockType] || 0) + 1; // Increment the type-specific counter

    const relativePositions = [
      // Direct neighbors (6)
      { x: -1, y: 0, z: 0 },
      { x: 1, y: 0, z: 0 },
      { x: 0, y: -1, z: 0 },
      { x: 0, y: 1, z: 0 },
      { x: 0, y: 0, z: -1 },
      { x: 0, y: 0, z: 1 },

      // Diagonals on same plane (12)
      { x: -1, y: 0, z: -1 },
      { x: -1, y: 0, z: 1 },
      { x: 1, y: 0, z: -1 },
      { x: 1, y: 0, z: 1 },
      { x: 0, y: -1, z: -1 },
      { x: 0, y: -1, z: 1 },
      { x: 0, y: 1, z: -1 },
      { x: 0, y: 1, z: 1 },
      { x: -1, y: -1, z: 0 },
      { x: -1, y: 1, z: 0 },
      { x: 1, y: -1, z: 0 },
      { x: 1, y: 1, z: 0 },
    ];

    // Get the recursion limit for the current block type
    const recursionLimit = forestryLogsPlusVanillaIndexCount[forestryLogsPlusVanillaArray.indexOf(initialBlockType)];

    // Recursive call for each adjacent and diagonal block
    relativePositions.forEach((offset) => {
      if (indexCheck >= recursionLimit) {
        return; // recursion limit stopper
      }
      const nextLocation = { x: blockx + offset.x, y: blocky + offset.y, z: blockz + offset.z };
      const nextBlock = dimension.getBlock(nextLocation);

      if (nextBlock) {
        const nextBlockType = nextBlock.typeId;
        if (
          isMatchingLogOrWood(nextBlockType, initialBlockType) ||
          getCorrespondingLeafType(initialBlockType).includes(nextBlockType)
        ) {
          pendingBlocks++; // Increment pending blocks for valid adjacent blocks
          system.runTimeout(() => {
            chainsawtree(player, nextBlock, nextLocation, initialBlockType, indexCheck + 1, firstLocation);
          }, 4);
        }
      }
    });

    decrementPendingBlocks(player.dimension, firstLocation); // Decrement pending blocks after processing this block
  } catch (e) {
    console.warn(`Error in chainsawtree: ${e}`);
    activeTreeChopping = false; // Ensure tree chopping is marked inactive on error
    stopItemGrouping(); // Ensure grouping stops on error
  }
}
