import { world } from "@minecraft/server";
import highlightBlock from "./multiblockOutlineBlock.js";
import { getAdjacentBlock, modules } from "./multiblockUtils.js";

const blockComponents = [
  {
    id: "pb_plane:multiblock_component",
    code: {
      onTick: (data) => {
        // Call the update method of multiblockManager from the onTick callback
        try {
          multiblockManager.update(data.block);
        } catch (error) {}
      },
    },
  },
];

class multiblockManager {
  static update(block) {
    const facingDirection = block.permutation.getState(
      "minecraft:cardinal_direction"
    );
    const closest = block.dimension.getEntities({
      maxDistance: 30,
      type: "minecraft:player",
    });
    if (!closest) return;
    ////////////////////////////////////////////////////// MACHINE CORE //////////////////////////////////////////////
    else if (block.typeId === "pb_plane:machine_core") {
      try {
        const connection = block.permutation.getState("pb_plane:mb_connection");
        if (connection == "single") return;
        const leftBlock = getAdjacentBlock(block, facingDirection, "left");
        const rightBlock = getAdjacentBlock(block, facingDirection, "right");

        if (
          (connection == "complete_right" &&
            !modules.includes(leftBlock.typeId)) ||
          (connection == "complete_left" &&
            !modules.includes(rightBlock.typeId))
        ) {
          this.resetToSingle(block, leftBlock, rightBlock);
        }
      } catch (error) {}
    }
    ////////////////////////////////////////////////////// ASSEMBLY CORE //////////////////////////////////////////////
    else if (block.typeId === "pb_plane:assembly_core") {
      if (block.permutation.getState("pb_plane:mb_connection") === "single") {
        const southBlock = block.dimension.getBlock({
          x: block.x,
          y: block.y,
          z: block.z + 1,
        });
        const eastBlock = block.dimension.getBlock({
          x: block.x + 1,
          y: block.y,
          z: block.z,
        });
        const southEastBlock = block.dimension.getBlock({
          x: block.x + 1,
          y: block.y,
          z: block.z + 1,
        });

        if (
          this.isAssemblyCore(eastBlock) &&
          this.isAssemblyCore(southBlock) &&
          this.isAssemblyCore(southEastBlock)
        ) {
          this.set2x2Multiblock(block, eastBlock, southBlock, southEastBlock);
          return;
        }
      } else if (
        block.permutation.getState("pb_plane:mb_connection") !== "single"
      ) {
        this.check2x2Integrity(block);
      }
    }
    ////////////////////////////////////////////////////// MODULE - NOT CONDENSER AS IT NEEDS TANK CHECKS //////////////////////////////////////////////
    else if (modules.includes(block.typeId)) {
      const leftBlock = getAdjacentBlock(block, facingDirection, "left");
      const rightBlock = getAdjacentBlock(block, facingDirection, "right");

      // Check if the adjacent blocks are loaded
      if (!leftBlock || !rightBlock) {
        //console.warn("Adjacent blocks are not loaded. Skipping checks.");
        return; // Stop execution if blocks are not loaded
      }

      if (
        leftBlock.permutation.getState("pb_plane:mb_connection") ==
          "complete_right" ||
        rightBlock.permutation.getState("pb_plane:mb_connection") ==
          "complete_left"
      )
        return;

      if (
        this.isCore(leftBlock) &&
        this.isCore(rightBlock) &&
        this.areAllBlocksFacingSameDirection(block, leftBlock, rightBlock) &&
        block.permutation.getState("pb_plane:mb_connection") != "complete"
      ) {
        this.setMultiBlock(block, leftBlock, rightBlock);
      } else if (
        (!this.isCore(leftBlock) ||
          !this.isCore(rightBlock) ||
          !this.areAllBlocksFacingSameDirection(
            block,
            leftBlock,
            rightBlock
          )) &&
        block.permutation.getState("pb_plane:mb_connection") == "complete"
      ) {
        this.resetToSingle(block, leftBlock, rightBlock);
      }
    }
    ////////////////////////////////////////////////////// CONDENSER TANK CHECK ///////////////////////////////////////
    if (block.typeId === "pb_plane:module_condenser") {
      const behindBlock = getAdjacentBlock(block, facingDirection, "behind");
      const leftBlock = getAdjacentBlock(block, facingDirection, "left");
      const rightBlock = getAdjacentBlock(block, facingDirection, "right");

      if (block.permutation.getState("pb_plane:mb_connection") === "single") {
        block.setPermutation(
          block.permutation.withState("pb_plane:has_tank", "false")
        );
      } else {
        if (block.permutation.getState("pb_plane:has_tank") === "false") {
          if (
            behindBlock.typeId === "pb_plane:fuel_tank" &&
            behindBlock.permutation.getState("pb_plane:mb_connection") ===
              "single"
          ) {
            const fuelQty = behindBlock.permutation.getState(
              "pb_plane:fuel_quantity"
            );
            block.setPermutation(
              block.permutation.withState("pb_plane:has_tank", "true")
            );
            block.setPermutation(
              block.permutation.withState("pb_plane:fuel_quantity", fuelQty)
            );
            leftBlock.setPermutation(
              leftBlock.permutation.withState("pb_plane:has_tank", "true")
            );
            leftBlock.setPermutation(
              leftBlock.permutation.withState("pb_plane:fuel_quantity", fuelQty)
            );
            rightBlock.setPermutation(
              rightBlock.permutation.withState("pb_plane:has_tank", "true")
            );
            rightBlock.setPermutation(
              rightBlock.permutation.withState(
                "pb_plane:fuel_quantity",
                fuelQty
              )
            );
            this.setTankConnectionState(behindBlock, facingDirection);
          }
        } else {
          try {
            if (
              behindBlock.typeId != "pb_plane:fuel_tank" ||
              behindBlock.permutation.getState("pb_plane:mb_connection") !=
                block.permutation.getState("minecraft:cardinal_direction")
            ) {
              block.setPermutation(
                block.permutation.withState("pb_plane:has_tank", "false")
              );
              block.setPermutation(
                block.permutation.withState("pb_plane:fuel_quantity", 0)
              );
              leftBlock.setPermutation(
                leftBlock.permutation.withState("pb_plane:has_tank", "false")
              );
              leftBlock.setPermutation(
                leftBlock.permutation.withState("pb_plane:fuel_quantity", 0)
              );
              rightBlock.setPermutation(
                rightBlock.permutation.withState("pb_plane:has_tank", "false")
              );
              rightBlock.setPermutation(
                rightBlock.permutation.withState("pb_plane:fuel_quantity", 0)
              );
            } else {
              const fuelQty = behindBlock.permutation.getState(
                "pb_plane:fuel_quantity"
              );
              block.setPermutation(
                block.permutation.withState("pb_plane:fuel_quantity", fuelQty)
              );
              leftBlock.setPermutation(
                leftBlock.permutation.withState(
                  "pb_plane:fuel_quantity",
                  fuelQty
                )
              );
              rightBlock.setPermutation(
                rightBlock.permutation.withState(
                  "pb_plane:fuel_quantity",
                  fuelQty
                )
              );
            }
          } catch (error) {}
        }
      }
    }
    ////////////////////////////////////////////////////// TANK CHECK - SEE IF CONDENSER IS STILL THERE AND FUNCTIONAL //////////////////////////////////////////////
    if (block.typeId === "pb_plane:fuel_tank") {
      if (block.permutation.getState("pb_plane:mb_connection") === "single") {
        return;
      }
      const direction = block.permutation.getState("pb_plane:mb_connection");

      let checkLocation;
      switch (direction) {
        case "north":
          checkLocation = block.south(1);
          break;
        case "south":
          checkLocation = block.north(1);
          break;
        case "east":
          checkLocation = block.west(1);
          break;
        case "west":
          checkLocation = block.east(1);
          break;
      }
      if (checkLocation.typeId != "pb_plane:module_condenser") {
        block.setPermutation(
          block.permutation.withState("pb_plane:mb_connection", "single")
        );
      }
      if (checkLocation.typeId === "pb_plane:module_condenser") {
        const moduleConnection = checkLocation.permutation.getState(
          "pb_plane:mb_connection"
        );
        if (moduleConnection === "single") {
          block.setPermutation(
            block.permutation.withState("pb_plane:mb_connection", "single")
          );
        }
      }
    }
  }

  static setTankConnectionState(behindBlock, facingDirection) {
    switch (facingDirection) {
      case "south":
        behindBlock.setPermutation(
          behindBlock.permutation.withState("pb_plane:mb_connection", "south")
        );
        break;
      case "north":
        behindBlock.setPermutation(
          behindBlock.permutation.withState("pb_plane:mb_connection", "north")
        );
        break;
      case "east":
        behindBlock.setPermutation(
          behindBlock.permutation.withState("pb_plane:mb_connection", "east")
        );
        break;
      case "west":
        behindBlock.setPermutation(
          behindBlock.permutation.withState("pb_plane:mb_connection", "west")
        );
        break;
      // Add more cases if you have additional directions
      default:
        break;
    }
  }

  static isCore(block) {
    return block && block.typeId === "pb_plane:machine_core";
  }

  static isAssemblyCore(block) {
    return (
      block &&
      block.typeId === "pb_plane:assembly_core" &&
      block.permutation.getState("pb_plane:mb_connection") === "single"
    );
  }

  static areAllBlocksFacingSameDirection(moduleBlock, leftBlock, rightBlock) {
    const moduleDirection = moduleBlock.permutation.getState(
      "minecraft:cardinal_direction"
    );
    return (
      leftBlock.permutation.getState("minecraft:cardinal_direction") ===
        moduleDirection &&
      rightBlock.permutation.getState("minecraft:cardinal_direction") ===
        moduleDirection
    );
  }

  // Update the multiblock structure
  static setMultiBlock(moduleBlock, leftBlock, rightBlock) {
    try {
      moduleBlock.setPermutation(
        moduleBlock.permutation.withState("pb_plane:mb_connection", "complete")
      );
      highlightBlock(moduleBlock, "yellow");

      let facing;
      const moduleDirection = moduleBlock.permutation.getState(
        "minecraft:cardinal_direction"
      );

      if (moduleDirection === "north") {
        facing = 0;
      } else if (moduleDirection === "east") {
        facing = 90;
      } else if (moduleDirection === "west") {
        facing = -90;
      } else if (moduleDirection === "south") {
        facing = 180;
      }

      const blockType = moduleBlock.typeId;
      const entityType = `${blockType}_entity`;
      const { x, y, z } = moduleBlock.location;
      moduleBlock.dimension.runCommandAsync(
        `summon ${entityType} ${x} ${y + 0.5} ${z} ${facing} 0`
      );
    } catch (error) {}

    try {
      leftBlock.setPermutation(
        leftBlock.permutation.withState(
          "pb_plane:mb_connection",
          "complete_left"
        )
      );
      highlightBlock(leftBlock, "yellow");
    } catch (error) {}

    try {
      rightBlock.setPermutation(
        rightBlock.permutation.withState(
          "pb_plane:mb_connection",
          "complete_right"
        )
      );
      highlightBlock(rightBlock, "yellow");
    } catch (error) {}
  }

  static set2x2Multiblock(block, eastBlock, southBlock, southEastBlock) {
    // Set each block's state based on its position
    block.setPermutation(
      block.permutation.withState(
        "pb_plane:mb_connection",
        "complete_north_west"
      )
    );
    eastBlock.setPermutation(
      eastBlock.permutation.withState(
        "pb_plane:mb_connection",
        "complete_north_east"
      )
    );
    southBlock.setPermutation(
      southBlock.permutation.withState(
        "pb_plane:mb_connection",
        "complete_south_west"
      )
    );
    southEastBlock.setPermutation(
      southEastBlock.permutation.withState(
        "pb_plane:mb_connection",
        "complete_south_east"
      )
    );

    // Highlight blocks to verify structure formation
    highlightBlock(block, "yellow");
    highlightBlock(eastBlock, "yellow");
    highlightBlock(southBlock, "yellow");
    highlightBlock(southEastBlock, "yellow");
  }

  static resetToSingle(moduleBlock, leftBlock, rightBlock) {
    if (moduleBlock) {
      try {
        moduleBlock.setPermutation(
          moduleBlock.permutation.withState("pb_plane:mb_connection", "single")
        );
        moduleBlock.dimension.runCommand(
          `execute positioned ${moduleBlock.x} ${moduleBlock.y} ${moduleBlock.z} run event entity @e[r=1] pb_plane:despawn`
        );
      } catch (error) {}
    }

    if (leftBlock) {
      try {
        leftBlock.setPermutation(
          leftBlock.permutation.withState("pb_plane:mb_connection", "single")
        );
      } catch (error) {}
    }

    if (rightBlock) {
      try {
        rightBlock.setPermutation(
          rightBlock.permutation.withState("pb_plane:mb_connection", "single")
        );
      } catch (error) {}
    }
  }
  static check2x2Integrity(block) {
    const currentPosition = block.permutation.getState(
      "pb_plane:mb_connection"
    );
    const { x, y, z } = block;
    if (currentPosition === "complete_north_east") {
      // Check if all other blocks are present and in the correct state
      const northWest = block.dimension.getBlock({ x: x - 1, y: y, z: z });
      const southEast = block.dimension.getBlock({ x: x, y: y, z: z + 1 });
      const southWest = block.dimension.getBlock({ x: x - 1, y: y, z: z + 1 });

      const blocksToCheck = [block, northWest, southEast, southWest];
      const allBlocksPresent = blocksToCheck.every(
        (b) =>
          b &&
          b.typeId === "pb_plane:assembly_core" &&
          b.permutation.getState("pb_plane:mb_connection") !== "single"
      );
      if (allBlocksPresent) {
      } else
        try {
          block.setPermutation(
            block.permutation.withState("pb_plane:mb_connection", "single")
          );
        } catch (error) {}
    }
    if (currentPosition === "complete_north_west") {
      const masterBlock = block.dimension.getBlock({ x: x + 1, y: y, z: z });
      if (
        masterBlock.permutation.getState("pb_plane:mb_connection") ===
        "complete_north_east"
      ) {
        this.check2x2Integrity(masterBlock);
      } else
        try {
          block.setPermutation(
            block.permutation.withState("pb_plane:mb_connection", "single")
          );
        } catch (error) {}
    }
    if (currentPosition === "complete_south_east") {
      const masterBlock = block.dimension.getBlock({ x: x, y: y, z: z - 1 });
      if (
        masterBlock.permutation.getState("pb_plane:mb_connection") ===
        "complete_north_east"
      ) {
        this.check2x2Integrity(masterBlock);
      } else
        try {
          block.setPermutation(
            block.permutation.withState("pb_plane:mb_connection", "single")
          );
        } catch (error) {}
    }
    if (currentPosition === "complete_south_west") {
      const masterBlock = block.dimension.getBlock({
        x: x + 1,
        y: y,
        z: z - 1,
      });
      if (
        masterBlock.permutation.getState("pb_plane:mb_connection") ===
        "complete_north_east"
      ) {
        this.check2x2Integrity(masterBlock);
      } else
        try {
          block.setPermutation(
            block.permutation.withState("pb_plane:mb_connection", "single")
          );
        } catch (error) {}
    }
  }
}

let reload = 0;

world.beforeEvents.worldInitialize.subscribe((data) => {
  reload++;
  if (reload > 1) return; // Prevent multiple registrations

  for (const comp of blockComponents) {
    data.blockComponentRegistry.registerCustomComponent(comp.id, comp.code);
  }
});
