import { world, BlockPermutation } from "@minecraft/server";
import { Vector3 } from "../Vector3";
import { randomInteger } from "../Random";
import { spawnParticle } from "../SpawnParticle";

const cropBlocks = {
  "minecraft:wheat": { growthVariable: "growth", maxGrowth: 7 },
  "minecraft:beetroot": { growthVariable: "growth", maxGrowth: 7 },
  "minecraft:carrots": { growthVariable: "growth", maxGrowth: 7 },
  "minecraft:potatoes": { growthVariable: "growth", maxGrowth: 7 },
  "minecraft:melon_stem": { growthVariable: "growth", maxGrowth: 7 },
  "minecraft:pumpkin_stem": { growthVariable: "growth", maxGrowth: 7 },
  "minecraft:torchflower_crop": { growthVariable: "growth", maxGrowth: 1 },
  "minecraft:pitcher_crop": { growthVariable: "growth", maxGrowth: 4 },
  "minecraft:bamboo": { growthVariable: "none" },
  "minecraft:reeds": { growthVariable: "none" },
  "minecraft:sweet_berry_bush": { growthVariable: "growth", maxGrowth: 3 },
  "minecraft:kelp": { growthVariable: "none" },
  "minecraft:sea_pickle": { growthVariable: "cluster_count", maxGrowth: 3 },
  "minecraft:nether_wart": { growthVariable: "age", maxGrowth: 3 },
  "minecraft:cactus": { growthVariable: "none" },
  "minecraft:bamboo_sapling": { growthVariable: "none" }
}

//Function run when using the spell
export function growSpell(player) {
  player.sendMessage(`<${player.nameTag}> Growth spell!`);
  const location = player.location;
  const dimension = player.dimension;
  spawnParticle("blockception_magic:grow_ring", location, dimension);
  spawnParticle("blockception_magic:grow_runes", location, dimension);
  spawnParticle("blockception_magic:grow_cloud", location, dimension);
  let posY = location.y;

  if (checkYPos(location.y)) {
    posY = location.y + 1;
  }

  for (let offsetX = -3; offsetX <= 3; offsetX++) {
    for (let offsetZ = -3; offsetZ <= 3; offsetZ++) {
      const x = location.x + offsetX;
      const y = posY;
      const z = location.z + offsetZ;

      const block = dimension.getBlock(new Vector3(x, y, z));
      if (block.typeId in cropBlocks) {
        growBlock(block, dimension);
      }
    }
  }
}

function checkAbove(dimension, location) {
  let yOffset = location.y;
  let blockAbove;

  while(true) {
    blockAbove = dimension.getBlock(new Vector3(location.x, yOffset, location.z));
    if (blockAbove.typeId == "minecraft:air") {
      break;
    }
    yOffset++
  }
  return blockAbove;
}

function growBlock(block, dimension) {
  const growthVariable = cropBlocks[block.typeId].growthVariable;
  if (growthVariable == "none" && block.typeId != "minecraft:bamboo_sapling") {
    let airBlock = checkAbove(dimension, block.location);
    airBlock.setPermutation(BlockPermutation.resolve(block.typeId));
    spawnParticle("blockception_magic:crop_grow", block.location, dimension);
    spawnParticle("blockception_magic:crop_grow_cloud", block.location, dimension);
  } else if (growthVariable == "none" && block.typeId == "minecraft:bamboo_sapling") {
    block.setPermutation(BlockPermutation.resolve("minecraft:bamboo"));
    let airBlock = checkAbove(dimension, block.location);
    airBlock.setPermutation(BlockPermutation.resolve("minecraft:bamboo"));
    spawnParticle("blockception_magic:crop_grow", block.location, dimension);
    spawnParticle("blockception_magic:crop_grow_cloud", block.location, dimension);
  } else {
    const blockGrowth = block.permutation.getState(growthVariable);
    if (blockGrowth >= cropBlocks[block.typeId].maxGrowth) {
      return;
    } else {
      let newGrowthState = Math.min(block.permutation.getState(growthVariable) + randomInteger(2, 4), cropBlocks[block.typeId].maxGrowth);
      block.setPermutation(block.permutation.withState(growthVariable, newGrowthState));
      spawnParticle("blockception_magic:crop_grow", block.location, dimension);
      spawnParticle("blockception_magic:crop_grow_cloud", block.location, dimension);
    }
  }
}

function checkYPos(value) {
  const fraction = value % 1;
  return (
    Math.abs(fraction) - 0.9375 == 0 ||
    Math.abs(fraction) - 0.875 == 0 ||
    Math.abs(fraction) - 0.0625 == 0 ||
    Math.abs(fraction) - 0.125 == 0
  )
}