import {
  world,
  system,
  MolangVariableMap,
  EntityDamageCause,
} from "@minecraft/server";
import { CurrentEventProp, AllEventProp } from "./utilities";

const eventId = "torch_event";

const torchesTypeIDs = [
  "minecraft:torch",
  "minecraft:soul_torch",
  "minecraft:redstone_torch",
];

export function torches_event_MAIN(dimension) {
  system.runInterval(() => {
    const event = CurrentEventProp.getProp();
    if (!(event.id == eventId && event.status == "is_happening")) return;
    if (event.timer < event.maxDuration) {
      if (event.timer == 1) {
        world.sendMessage([
          {
            translate: `tvf_randev.event.start.${event.id}`,
          },
        ]);
      }
      const players = dimension.getPlayers();
      const player = players[Math.floor(Math.random() * players.length)];

      players.forEach((p) => {
        if (player.graphicsMode == "Deferred") {
          p.runCommand(
            "/fog @s push tvf_randev:torch_rebellion_vol tvf_randev:fogsID"
          );
        } else {
          p.runCommand(
            "/fog @s push tvf_randev:torch_rebellion_fog tvf_randev:fogsID"
          );
        }
      });

      if (system.currentTick % 40 == 0) {
        findTorchNear(dimension, player, {
          x: 10,
          y: 4,
          z: 10,
        }).then((torches) => {
          for (let torch of torches) {
            const tickDelay = Math.floor(20 + Math.random() * 20);
            //warning particle
            system.runTimeout(() => {
              let map1 = new MolangVariableMap();
              map1.setFloat("variant", torch.variant);
              dimension.spawnParticle(
                "tvf_randev:torch_rebellion_warning",
                {
                  x: torch.location.x + 0.5,
                  y: torch.location.y + 0.7,
                  z: torch.location.z + 0.5,
                },
                map1
              );
            }, tickDelay - 20);
            //start shooting
            system.runTimeout(() => {
              let map = new MolangVariableMap();
              map.setFloat("x", player.location.x - torch.location.x - 0.5);
              map.setFloat("y", player.location.y + 1 - torch.location.y);
              map.setFloat("z", player.location.z - torch.location.z - 0.5);
              map.setFloat("variant", torch.variant);
              dimension.spawnParticle(
                "tvf_randev:torch_rebellion",
                {
                  x: torch.location.x + 0.5,
                  y: torch.location.y + 0.5,
                  z: torch.location.z + 0.5,
                },
                map
              );
              dimension.playSound("mob.blaze.shoot", torch.location);
              const tempLocation = player.location;
              //time to run away
              system.runTimeout(() => {
                if (
                  Math.floor(player.location.x) == Math.floor(tempLocation.x) &&
                  Math.floor(player.location.z) == Math.floor(tempLocation.z)
                )
                  player.applyDamage(1, {
                    cause: EntityDamageCause.fire,
                  });
              }, 10);
            }, tickDelay);
          }
        });
      }
      event.timer += 1;
    }
    if (event.forcedEnd == true || event.timer >= event.maxDuration) {
      event.status = "is_end";
      dimension.runCommand("/fog @a remove tvf_randev:fogsID");
      world.sendMessage([
        {
          translate: `tvf_randev.event.end.${event.id}`,
        },
      ]);
    }
    CurrentEventProp.update(event);
  });
}
function findTorchNear(dimension, player, region) {
  const offset = {
    x: (-1 * region.x) / 2,
    y: (-1 * region.y) / 2,
    z: (-1 * region.z) / 2,
  };
  return new Promise((resolve, reject) => {
    let torchesCoordsList = [];
    system.runJob(
      (function* () {
        for (let i = offset.x; i < region.x - offset.x; i++) {
          for (let j = offset.y; j < region.y - offset.y; j++) {
            for (let k = offset.z; k < region.z - offset.z; k++) {
              try {
                let coords = {
                  x: Math.floor(player.location.x) + i,
                  y: Math.floor(player.location.y) + j,
                  z: Math.floor(player.location.z) + k,
                };
                let block = dimension.getBlock(coords);
                if (block) {
                  if (torchesTypeIDs.includes(block.typeId)) {
                    let variant =
                      block.typeId == "minecraft:redstone_torch"
                        ? 2
                        : block.typeId == "minecraft:soul_torch"
                        ? 1
                        : 0;
                    torchesCoordsList.push({
                      location: coords,
                      variant: variant,
                    });
                  }
                }
              } catch {}
              yield;
            }
          }
        }
        resolve(torchesCoordsList);
      })()
    );
  });
}

//torch event avalible condition
world.afterEvents.playerPlaceBlock.subscribe((event) => {
  const events = AllEventProp.getProp();
  if (
    torchesTypeIDs.includes(event.block.typeId) &&
    events[eventId].is_available === false
  ) {
    events[eventId].is_available = true;
    AllEventProp.update(events);
  }
});
