import { system, world, ItemStack } from "@minecraft/server";
import { blockToBiomeMap, DP, ignoreBlocks } from "./biome/ambient_handler";

// === NEW: timing + animation constants ===
const TICKS_PER_SECOND = 20;
const PARTICLE_INTERVAL_TICKS = 5 * TICKS_PER_SECOND; // 5 seconds
const PARTICLE_ANIM = "animation.hb_hr.vfx_handler.particle";

export class vfxHandler {
  static initialized = false;
  static playerBiomeMap = new Map(); // Speichert zuletzt erkannte Biome für jeden Spieler

  constructor() {
    this.initialize();
  }

  initialize() {
    if (!vfxHandler.initialized) {
      vfxHandler.initialized = true;
      this.processSubscriptions();
    }
  }

  processSubscriptions() {
    let curTick = 0;
    const INIT_TIME = 0;

    world.afterEvents.playerSpawn.subscribe((event) => {
      const playerVfxHandlerTag = "hb_hr:" + event.player.id;
      event.player.runCommand(
        "/event entity @e[type=hb_hr:vfx_handler,tag=" + playerVfxHandlerTag + "] hb_hr:despawn"
      );
      let velocity = event.player.getVelocity();
      let loc = {
        x: event.player.location.x,
        y: event.player.location.y + (event.player.isSneaking ? 1.3 : 1.6),
        z: event.player.location.z,
      };
      const allVfxHandler = event.player.dimension.getEntities({
        type: "hb_hr:vfx_handler",
        tags: [playerVfxHandlerTag],
      });
      try {
        if (allVfxHandler.length > 0 || !allVfxHandler) {
          allVfxHandler.forEach((vfxHandler) => {
            if (!vfxHandler.isValid()) return;
            vfxHandler.teleport(loc);
            vfxHandler.applyImpulse(velocity);
            vfxHandler.playAnimation("animation.hb_hr.red_moon.turn_on", {
              players: [event.player.name],
            });
          });
        } else {
          let newVfxHandler = event.player.dimension.spawnEntity("hb_hr:vfx_handler", loc);
          newVfxHandler.addTag(playerVfxHandlerTag);
        }
      } catch (error) {}
    });

    system.runInterval(() => {
      try {
        if (curTick > INIT_TIME) {
          const allPlayers = world.getAllPlayers();
          allPlayers.forEach((player) => {
            if (!player.isValid()) return;
            if (player.dimension.id != "minecraft:overworld") return;
            this.handleVfxDisplay(player, curTick);
          });
        }
        curTick++;
      } catch (e) {
        // console.warn(e);
      }
    }, 0);
  }

  handleVfxDisplay(player, curTick) {
    const raw = biomeCheck(player);
    const last = player.getDynamicProperty(DP.lastBiome) || "default";
    const curr = raw === null ? last : raw;

    const playerVfxHandlerTag = "hb_hr:" + player.id;
    let velocity = player.getVelocity();
    let loc = {
      x: player.location.x,
      y: player.location.y + (player.isSneaking ? 1.3 : 1.6),
      z: player.location.z,
    };
    const allVfxHandler = player.dimension.getEntities({
      type: "hb_hr:vfx_handler",
      tags: [playerVfxHandlerTag],
    });
    try {
      if (allVfxHandler.length > 0) {
        allVfxHandler.forEach((vfxHandler) => {
          if (!vfxHandler.isValid()) return;
          vfxHandler.teleport(loc);
          vfxHandler.applyImpulse(velocity);
          vfxHandler.playAnimation("animation.hb_hr.red_moon.turn_on", { players: [player.name] });

          // === NEW: play the particle animation every 5 seconds for the linked player only ===
          if (curTick % PARTICLE_INTERVAL_TICKS === 0) {
            vfxHandler.playAnimation(PARTICLE_ANIM, { players: [player.name] });
          }

          if (curr) {
            vfxHandler.setProperty("hb_hr:biome", curr);
          }
        });
      } else {
        let newVfxHandler = player.dimension.spawnEntity("hb_hr:vfx_handler", loc);
        newVfxHandler.addTag(playerVfxHandlerTag);
      }
    } catch (error) {}
  }
}

function biomeCheck(player) {
  if (player.hasTag("hb_hr_on_banned_wither_arena")) return "banned_wither";

  const dim = player.dimension;
  const down = { x: 0, y: -1, z: 0 };

  // only sample *once* at the player's feet
  const hit = dim.getBlockFromRay(player.location, down);
  if (!hit?.block) {
    // nothing underfoot → no change
    return null;
  }

  const id = hit.block.typeId;
  if (ignoreBlocks.has(id)) {
    // stepping on a decorative/ignore block → signal “keep last”
    return null;
  }
  // real ground → map to biome (or vanilla)
  if (!blockToBiomeMap[id]) {
    return "default";
  } else {
    return blockToBiomeMap[id] || "none";
  }
}

// === FOG TRANSITION LOGIC ===
function updatePropertyOnEntity(player, currBiome, settings) {
  const lastBiome = player.getDynamicProperty(DP.lastBiome) || "default";

  // 1) BIOME CHANGED
  if (currBiome !== lastBiome) {
    // remove *any* fog that might still be applied:
    Object.values(fogIds).forEach((fid) => {
      if (fid) popFog(player, fid);
    });
    // if the new biome wants fog → push it
    if (wantFog && fogIds[currBiome]) {
      pushFog(player, fogIds[currBiome]);
    }
  }
  // 2) SAME BIOME, FOG TOGGLED IN-PLACE
  else if (wantFog !== hadFogBefore) {
    if (wantFog && fogIds[currBiome]) {
      pushFog(player, fogIds[currBiome]);
    } else if (!wantFog && fogIds[currBiome]) {
      popFog(player, fogIds[currBiome]);
    }
  }
  // 3) ENTERING A BIO–FOG-OFF ZONE
  //    (covered by the first branch: wantFog===false → pop all)

  // 4) ENTERING A BIO–FOG-ON ZONE
  //    (covered by the first branch: wantFog===true → pop all then push only the new)

  // persist for next tick & for UI logic
  player.setDynamicProperty(DP.lastBiome, currBiome);
}
