import * as mc from "@minecraft/server";
import * as vector from "./utils/vector";
import * as selectors from "./utils/selectors";

// gravity
/**
 *
 * @param {mc.WorldInitializeBeforeEvent} event
 */
export function registerComponent(event) {
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:raked_sand", {
    onTick(e) {
      const block = e.block;
      if (block.below().typeId === "minecraft:air") {
        const ent = block.dimension.spawnEntity(
          "hf_mzs:falling_raked_sand",
          vector.add(block.location, { x: 0.5, y: 0, z: 0.5 })
        );
        ent.setProperty("hf_mzs:red", block.typeId === "hf_mzs:red_raked_sand");
        ent.setProperty("hf_mzs:cardinal_direction", block.permutation.getState("minecraft:cardinal_direction"));
        ent.setProperty("hf_mzs:corner", block.permutation.getState("hf_mzs:corner"));
        ent.setProperty("hf_mzs:north_east", block.permutation.getState("hf_mzs:north_east"));
        ent.setProperty("hf_mzs:north_west", block.permutation.getState("hf_mzs:north_west"));
        ent.setProperty("hf_mzs:south_east", block.permutation.getState("hf_mzs:south_east"));
        ent.setProperty("hf_mzs:south_west", block.permutation.getState("hf_mzs:south_west"));
        block.dimension.setBlockType(block.location, "minecraft:air");
        return;
      }
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:deepslate_base", {
    onTick(e) {
      const block = e.block;
      const deepslateList = ["minecraft:cobbled_deepslate", "minecraft:polished_deepslate"];
      const notAllowBlocks = [
        "minecraft:deepslate_stairs",
        "minecraft:dark_oak_slab",
        "minecraft:dark_oak_fence",
        "minecraft:dark_oak_fence_gate",
        "minecraft:dark_oak_double_slab",
        "minecraft:deepslate_wall",
        "minecraft:dark_oak_trapdoor",
      ];
      block.setPermutation(mc.BlockPermutation.resolve("minecraft:cobbled_deepslate"));
      placeDeepslate(block.location, block.dimension);
      function placeDeepslate(blockLocation, dimension) {
        const index = selectors.getRandomQuantity(0, 1);
        let location = blockLocation;
        location.y -= 1;
        const newBlock = dimension.getBlock(location);
        const topSolidBlock = block.dimension.getTopmostBlock(location, location.y);
        const height = topSolidBlock.location.y - location.y;
        if (height < 0 || notAllowBlocks.includes(topSolidBlock.typeId)) {
          newBlock.setPermutation(mc.BlockPermutation.resolve(deepslateList[index]));
          placeDeepslate(location, dimension);
        } else {
          block.setPermutation(mc.BlockPermutation.resolve(deepslateList[index]));
          return;
        }
      }
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:white_concrete_wall", {
    onTick(e) {
      const block = e.block;
      const wallList = ["minecraft:white_concrete", "minecraft:diorite", "minecraft:calcite"];
      const index = selectors.getRandomQuantity(0, 2);
      try {
        block.setPermutation(mc.BlockPermutation.resolve(wallList[index]));
      } catch {}
      const interval = mc.system.runInterval(() => {
        try {
          const notAllowList = [
            "minecraft:dark_oak_button",
            "minecraft:cobbled_deepslate",
            "minecraft:polished_deepslate",
            "minecraft:cobbled_deepslate_stairs",
            "minecraft:deepslate_wall",
            "minecraft:dark_oak_slab",
            "minecraft:dark_oak_stairs",
            "minecraft:dark_oak_trapdoor",
            "minecraft:dark_oak_fence",
            "minecraft:lantern",
            "minecraft:birch_fence_gate",
          ];
          const newBlock = block.dimension.getBlock(block.location);
          if (notAllowList.includes(newBlock.typeId)) {
            block.setPermutation(mc.BlockPermutation.resolve(wallList[index]));
          }
        } catch {}
      }, 5);
      mc.system.runTimeout(() => {
        mc.system.clearRun(interval);
      }, 30);
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:hanging_roots", {
    onTick(e) {
      const block = e.block;
      const random = Math.random();
      if (random < 0.4) {
        try {
          block.setPermutation(mc.BlockPermutation.resolve("minecraft:hanging_roots"));
        } catch {}
      } else block.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:dirt_base", {
    onTick(e) {
      const block = e.block;
      const notAllowBlocks = [
        "minecraft:deepslate_stairs",
        "minecraft:dark_oak_slab",
        "minecraft:dark_oak_fence",
        "minecraft:dark_oak_fence_gate",
        "minecraft:dark_oak_double_slab",
        "minecraft:deepslate_wall",
        "minecraft:dark_oak_trapdoor",
      ];
      block.setPermutation(mc.BlockPermutation.resolve("minecraft:grass_block"));
      placeDirt(block.location, block.dimension);
      function placeDirt(blockLocation, dimension) {
        let location = blockLocation;
        location.y -= 1;
        const newBlock = dimension.getBlock(location);
        const topSolidBlock = block.dimension.getTopmostBlock(location, location.y);
        const height = topSolidBlock.location.y - location.y;
        if (height < 0 || notAllowBlocks.includes(topSolidBlock.typeId)) {
          newBlock.setPermutation(mc.BlockPermutation.resolve("minecraft:dirt"));
          placeDirt(location, dimension);
        } else {
          block.setPermutation(mc.BlockPermutation.resolve("minecraft:dirt"));
          return;
        }
      }
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:andesite_stairs", {
    onTick(e) {
      const block = e.block;
      const wallList = ["minecraft:polished_andesite_stairs", "minecraft:andesite_stairs"];
      const index = selectors.getRandomQuantity(0, 1);
      const cardinal = block.permutation.getState("minecraft:cardinal_direction");
      //mc.world.sendMessage(`${cardinal} ${cardinalToNum(cardinal)}`)
      try {
        block.setPermutation(
          mc.BlockPermutation.resolve(wallList[index], { weirdo_direction: cardinalToNum(cardinal) })
        );
      } catch {}
      function cardinalToNum(cardinal) {
        let result = 0;
        switch (cardinal) {
          case "east":
            result = 0;
            break;
          case "west":
            result = 1;
            break;
          case "south":
            result = 2;
            break;
          case "north":
            result = 3;
            break;
        }
        return result;
      }
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:deepslate_wall", {
    onTick(e) {
      const block = e.block;
      const wallList = ["minecraft:cobbled_deepslate_wall", "minecraft:polished_deepslate_wall"];
      const index = selectors.getRandomQuantity(0, 1);
      try {
        block.setPermutation(mc.BlockPermutation.resolve(wallList[index]));
      } catch {}
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:polished_andesite", {
    onTick(e) {
      const block = e.block;
      const wallList = ["minecraft:andesite", "minecraft:polished_andesite"];
      const index = selectors.getRandomQuantity(0, 1);
      try {
        block.setPermutation(mc.BlockPermutation.resolve(wallList[index]));
      } catch {}
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:clawed_log", {
    onTick(e) {
      if (Math.random() < 0.5) {
        e.block.setPermutation(mc.BlockPermutation.resolve(e.block.typeId, { "hf_mzs:variant": 1 }));
      }
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:water_replacer_dummy", {
    onTick(e) {
      const block = e.block;
      block.dimension.setBlockType(block.location, "minecraft:air");
    },
  });
  event.blockComponentRegistry.registerCustomComponent("hf_mzs:structure_gen_trigger", {
    onTick(e) {
      const block = e.block;
      if (block.isValid()) {
        const p = block.dimension.getEntities({ location: block.location, maxDistance: 128, type: "minecraft:player" });
        if (p.length > 0) {
          const loc = block.location;
          loc.x = Math.floor(loc.x) + 0.5;
          loc.y = Math.floor(loc.y);
          loc.z = Math.floor(loc.z) + 0.5;
          const e = block.dimension.getEntities({
            location: block.location,
            maxDistance: 5,
            type: "hf_mzs:umvuthi_gen_trigger",
          });
          if (e.length === 0) {
            const en = block.dimension.spawnEntity(block.typeId, loc);
            if (en && en.isValid()) {
              const rot = (Math.floor(Math.random() * 4) - 2) * 90;
              en.runCommand(`/tp @s ~ ~ ~ ${rot} 0`);
              block.setType("minecraft:air");
            }
          }
        }
      }
    },
  });
}

export function onBlockUpdate(event) {
  const { block, player } = event;
  if (block.typeId.includes("hf_mzs") && block.typeId.includes("raked_sand")) rakedSandUpdate(block, player);
}

export function rakedSandUpdate(block, player) {
  const north = block.north();
  const east = block.east();
  const south = block.south();
  const west = block.west();

  if (north.hasTag("hf_mzs:raked_sand")) {
    if (north.permutation.withState("hf_mzs:corner", false)) {
      if (resolveAxis(block) !== resolveAxis(north)) {
        if (resolveOrientation(block) === "east") {
          block.setPermutation(
            mc.BlockPermutation.resolve(block.typeId, { "hf_mzs:corner": true, "hf_mzs:south_east": true })
          );
        } else if (resolveOrientation(block) === "west") {
          block.setPermutation(
            mc.BlockPermutation.resolve(block.typeId, { "hf_mzs:corner": true, "hf_mzs:south_west": true })
          );
        } else if (resolveOrientation(block) === "north" || resolveOrientation(block) === "south") {
          let oc = getConnections(north);
          if (oc.length < 2 && resolveOrientation(north) === "east") {
            north.setPermutation(
              mc.BlockPermutation.resolve(north.typeId, { "hf_mzs:corner": true, "hf_mzs:north_east": true })
            );
          } else if (oc.length < 2 && resolveOrientation(north) === "west") {
            north.setPermutation(
              mc.BlockPermutation.resolve(north.typeId, { "hf_mzs:corner": true, "hf_mzs:north_west": true })
            );
          }
        }
      } else {
        //
      }
    }
  }
  if (east.hasTag("hf_mzs:raked_sand")) {
    if (east.permutation.withState("hf_mzs:corner", false)) {
      if (resolveAxis(block) !== resolveAxis(east)) {
        if (resolveOrientation(block) === "north") {
          block.setPermutation(
            mc.BlockPermutation.resolve(block.typeId, { "hf_mzs:corner": true, "hf_mzs:north_east": true })
          );
        } else if (resolveOrientation(block) === "south") {
          block.setPermutation(
            mc.BlockPermutation.resolve(block.typeId, { "hf_mzs:corner": true, "hf_mzs:south_west": true })
          );
        } else if (resolveOrientation(block) === "east" || resolveOrientation(block) === "west") {
          let oc = getConnections(east);
          if (oc.length < 2 && resolveOrientation(east) === "north") {
            east.setPermutation(
              mc.BlockPermutation.resolve(east.typeId, { "hf_mzs:corner": true, "hf_mzs:south_east": true })
            );
          } else if (oc.length < 2 && resolveOrientation(east) === "south") {
            east.setPermutation(
              mc.BlockPermutation.resolve(east.typeId, { "hf_mzs:corner": true, "hf_mzs:north_west": true })
            );
          }
        }
      } else {
        //
      }
    }
  }
  if (south.hasTag("hf_mzs:raked_sand")) {
    if (south.permutation.withState("hf_mzs:corner", false)) {
      if (resolveAxis(block) !== resolveAxis(south)) {
        if (resolveOrientation(block) === "east") {
          block.setPermutation(
            mc.BlockPermutation.resolve(block.typeId, { "hf_mzs:corner": true, "hf_mzs:north_west": true })
          );
        } else if (resolveOrientation(block) === "west") {
          block.setPermutation(
            mc.BlockPermutation.resolve(block.typeId, { "hf_mzs:corner": true, "hf_mzs:north_east": true })
          );
        } else if (resolveOrientation(block) === "north" || resolveOrientation(block) === "south") {
          let oc = getConnections(south);
          if (oc.length < 2 && resolveOrientation(south) === "east") {
            south.setPermutation(
              mc.BlockPermutation.resolve(south.typeId, { "hf_mzs:corner": true, "hf_mzs:south_west": true })
            );
          } else if (oc.length < 2 && resolveOrientation(south) === "west") {
            south.setPermutation(
              mc.BlockPermutation.resolve(south.typeId, { "hf_mzs:corner": true, "hf_mzs:south_east": true })
            );
          }
        }
      } else {
        //
      }
    }
  }
  if (west.hasTag("hf_mzs:raked_sand")) {
    if (west.permutation.withState("hf_mzs:corner", false)) {
      if (resolveAxis(block) !== resolveAxis(west)) {
        if (resolveOrientation(block) === "north") {
          block.setPermutation(
            mc.BlockPermutation.resolve(block.typeId, { "hf_mzs:corner": true, "hf_mzs:north_west": true })
          );
        } else if (resolveOrientation(block) === "south") {
          block.setPermutation(
            mc.BlockPermutation.resolve(block.typeId, { "hf_mzs:corner": true, "hf_mzs:south_east": true })
          );
        } else if (resolveOrientation(block) === "east" || resolveOrientation(block) === "west") {
          let oc = getConnections(west);
          if (oc.length < 2 && resolveOrientation(west) === "north") {
            west.setPermutation(
              mc.BlockPermutation.resolve(west.typeId, { "hf_mzs:corner": true, "hf_mzs:south_west": true })
            );
          } else if (oc.length < 2 && resolveOrientation(west) === "south") {
            west.setPermutation(
              mc.BlockPermutation.resolve(west.typeId, { "hf_mzs:corner": true, "hf_mzs:north_east": true })
            );
          }
        }
      } else {
        //
      }
    }
  }
}

function resolveAxis(block) {
  const blockRotation = block.permutation.getState("minecraft:cardinal_direction");
  if (blockRotation === "north" || blockRotation === "south") return 0;
  if (blockRotation === "east" || blockRotation === "west") return 1;
}

function resolveOrientation(block) {
  return block.permutation.getState("minecraft:cardinal_direction");
}

function getConnections(block) {
  const north = block.north();
  const east = block.east();
  const south = block.south();
  const west = block.west();

  const connections = [];

  if (north.hasTag("hf_mzs:raked_sand")) {
    if (north.permutation.withState("hf_mzs:corner", false)) {
      connections.push(north);
    }
  }
  if (east.hasTag("hf_mzs:raked_sand")) {
    if (east.permutation.withState("hf_mzs:corner", false)) {
      connections.push(east);
    }
  }
  if (south.hasTag("hf_mzs:raked_sand")) {
    if (south.permutation.withState("hf_mzs:corner", false)) {
      connections.push(south);
    }
  }
  if (west.hasTag("hf_mzs:raked_sand")) {
    if (west.permutation.withState("hf_mzs:corner", false)) {
      connections.push(west);
    }
  }

  return connections;
}
