// index.js
import { world, system, EquipmentSlot } from "@minecraft/server";
import { ActionFormData, ModalFormData } from "@minecraft/server-ui";
import { isRedMoon } from ".././moon/moon_handler";

// === CONFIG ===

const SETTINGS_ITEM = "hb_hr:ambient_handler_item"; // item used to open the settings UI

// Blocks that shouldn’t count as “ground” when determining biome:
export const ignoreBlocks = new Set([
  "minecraft:bed",
  "minecraft:water",
  "minecraft:flowing_water",
  "minecraft:lava",
  "minecraft:flowing_lava",
  "minecraft:grass_path",
  "minecraft:mossy_cobblestone",
  "hb_hr:ash_block",
  // put into the ignore list because of the b2 villages
  "hb_hr:cursed_planks",
  "hb_hr:cursed_roof",
  "hb_hr:grim_stone_bricks",
  "hb_hr:infested_grim_stone_bricks",
  "hb_hr:grim_stone_bricks_slab",
  // add any other decorative blocks here…
]);

// Map any block → biome key:
export const blockToBiomeMap = {
  "hb_hr:dried_dirt": "b1", // dead forest
  "hb_hr:rotten_soil": "b1", // dead forest
  "hb_hr:dead_roots": "b1", // dead forest
  "hb_hr:grim_stone_chunks": "b1", // dead forest
  "hb_hr:grim_stone": "b1", // dead forest
  "hb_hr:grim_stone_bricks": "b1", // dead forest
  "hb_hr:dirty_dead_roots": "b1", // dead forest
  "hb_hr:dead_bush": "b1", // dead forest
  "hb_hr:blight_log": "b1", // dead forest
  "hb_hr:dead_grass": "b1", // dead forest
  "hb_hr:hive": "b1", // dead forest
  "hb_hr:hive_carpet": "b1", // dead forest
  "hb_hr:hive_carpet_block": "b1", // dead forest
  "hb_hr:large_hive_egg": "b1", // dead forest
  "hb_hr:small_hive_egg": "b1", // dead forest

  "hb_hr:cursed_grass_block": "b2", // cursed meadows
  "hb_hr:dried_cursed_grass_block": "b2", // cursed meadows
  "hb_hr:cursed_grass": "b2", // cursed meadows
  "hb_hr:cursed_tall_grass": "b2", // cursed meadows
  "hb_hr:cursed_log": "b2", // cursed meadows
  "hb_hr:bone_pile_b2_0": "b2", // cursed meadows
  "hb_hr:bone_pile_b2_1": "b2", // cursed meadows
  "hb_hr:bone_pile_b2_2": "b2", // cursed meadows
  "hb_hr:bone_pile_small_0": "b2", // cursed meadows
  "hb_hr:bone_pile_small_1": "b2", // cursed meadows
  "hb_hr:bone_pile_small_2": "b2", // cursed meadows
  "hb_hr:bone_pile_small_3": "b2", // cursed meadows
  "hb_hr:bone_pile_small_4": "b2", // cursed meadows

  "hb_hr:mushroom_litter": "b3", // black forest
  "hb_hr:black_grass_block": "b3", // black forest
  "hb_hr:black_puddle": "b3", // black forest
  "hb_hr:black_moss": "b3", // black forest
  "hb_hr:black_leaves": "b3", // black forest
  "hb_hr:black_grass": "b3", // black forest
  "hb_hr:black_tall_grass": "b3", // black forest
  "hb_hr:black_rose": "b3", // black forest
  // add more block→biome mappings here…
};

// Fog‐IDs for each biome:
const fogIds = {
  red_moon: "hb_hr:red_moon",
  default: "hb_hr:vanilla",
  vanilla: "hb_hr:vanilla",
  banned_wither: "hb_hr:banned_wither",

  b1: "hb_hr:dead_forest",
  b2: "hb_hr:cursed_meadows",
  b3: "hb_hr:black_forest",

  // NEW: VV fog variants (set to your new fog defs)
  vv_b1: "hb_hr:vv_dead_forest",
  vv_b2: "hb_hr:vv_cursed_meadows",
  vv_b3: "hb_hr:vv_black_forest",

  vv_red_moon: "hb_hr:vv_red_moon",
  vv_default: "hb_hr:vv_vanilla",
  vv_vanilla: "hb_hr:vv_vanilla",
  vv_banned_wither: "hb_hr:vv_banned_wither",
};

const musicIds = {
  red_moon: "hb_hr_red_moon_music",
  vanilla: "hb_hr_dead_forest_music",
  default: "hb_hr_dead_forest_music",
  none: "hb_hr_dead_forest_music",
  banned_wither: "hb_hr_banned_wither_music",
  b1: "hb_hr_dead_forest_music",
  b2: "hb_hr_cursed_meadows_music",
  b3: "hb_hr_black_forest_music",
};

// Other particle‐based effects per biome:
const soundIds = {
  b1: ["hb_hr:b1_noise_0", "hb_hr:b1_noise_1", "hb_hr:b1_noise_2", "hb_hr:b1_noise_3", "hb_hr:b1_noise_4", "hb_hr:b1_noise_5", "hb_hr:b1_noise_6"],
  b2: ["hb_hr:b2_noise_0", "hb_hr:b2_noise_1", "hb_hr:b2_noise_2", "hb_hr:b2_noise_3", "hb_hr:b2_noise_4", "hb_hr:b2_noise_5"],
  b3: ["hb_hr:b3_noise_0", "hb_hr:b3_noise_1", "hb_hr:b3_noise_2", "hb_hr:b3_noise_3", "hb_hr:b3_noise_4", "hb_hr:b3_noise_5"],
  redmoon: ["hb_hr:rm_noise_0", "hb_hr:rm_noise_1", "hb_hr:rm_noise_2", "hb_hr:rm_noise_3", "hb_hr:rm_noise_4"],
  banned_wither: [],
  default: [],
  none: [],
};

// Other particle‐based effects per biome:
const biomeEffectsByQuality = {
  b1: {
    low: ["hb_hr:b1_fog_spawner_low", "hb_hr:b1_wind_spawner_low"],
    medium: ["hb_hr:b1_fog_spawner_medium", "hb_hr:b1_wind_spawner_medium"],
    high: ["hb_hr:b1_fog_spawner_high", "hb_hr:b1_wind_spawner_high"],
  },

  vv_b1: {
    low: ["hb_hr:vv_b1_wind_spawner_low"],
    medium: ["hb_hr:vv_b1_wind_spawner_medium"],
    high: ["hb_hr:vv_b1_wind_spawner_high"],
    // low: ["hb_hr:vv_b1_fog_spawner_low", "hb_hr:vv_b1_wind_spawner_low", "hb_hr:vv_b1_extra_low"],
    // medium: ["hb_hr:vv_b1_fog_spawner_medium", "hb_hr:vv_b1_wind_spawner_medium", "hb_hr:vv_b1_extra_medium"],
    // high: ["hb_hr:vv_b1_fog_spawner_high", "hb_hr:vv_b1_wind_spawner_high", "hb_hr:vv_b1_extra_high"],
  },
  b2: {
    low: ["hb_hr:b2_fog_spawner_low", "hb_hr:b2_dust_spawner_low"],
    medium: ["hb_hr:b2_fog_spawner_medium", "hb_hr:b2_dust_spawner_medium"],
    high: ["hb_hr:b2_fog_spawner_high", "hb_hr:b2_dust_spawner_high"],
  },
  vv_b2: {
    low: ["hb_hr:vv_b2_dust_spawner_low"],
    medium: ["hb_hr:vv_b2_dust_spawner_medium"],
    high: ["hb_hr:vv_b2_dust_spawner_high"],
  },
  b3: {
    low: ["hb_hr:b3_fog_spawner_low", "hb_hr:b3_mist_spawner_low", "hb_hr:b3_dust_spawner_low"],
    medium: ["hb_hr:b3_fog_spawner_medium", "hb_hr:b3_mist_spawner_medium", "hb_hr:b3_dust_spawner_medium"],
    high: ["hb_hr:b3_fog_spawner_high", "hb_hr:b3_mist_spawner_high", "hb_hr:b3_dust_spawner_high"],
  },
  vv_b3: {
    low: ["hb_hr:vv_b3_dust_spawner_low"],
    medium: ["hb_hr:vv_b3_dust_spawner_medium"],
    high: ["hb_hr:vv_b3_dust_spawner_high"],
  },
  red_moon: {
    low: ["hb_hr:rm_fog_spawner_low", "hb_hr:rm_mist_spawner_low", "hb_hr:rm_dust_spawner_low"],
    medium: ["hb_hr:rm_fog_spawner_medium", "hb_hr:rm_mist_spawner_medium", "hb_hr:rm_dust_spawner_medium"],
    high: ["hb_hr:rm_fog_spawner_high", "hb_hr:rm_mist_spawner_high", "hb_hr:rm_dust_spawner_high"],
  },

  vv_red_moon: {
    low: ["hb_hr:vv_rm_dust_spawner_low"],
    medium: ["hb_hr:vv_rm_dust_spawner_medium"],
    high: ["hb_hr:vv_rm_dust_spawner_high"],
  },
  banned_wither: {
    low: [],
    medium: [],
    high: [],
  },
  default: {
    low: [
      /*"hb_hr:vanilla_fog_spawner_low"*/
    ],
    medium: [
      /*"hb_hr:vanilla_fog_spawner_medium"*/
    ],
    high: [
      /*"hb_hr:vanilla_fog_spawner_high"*/
    ],
  },
};

// === GENERAL END PARTICLES BY QUALITY ===
const generalVanillaParticlesByQuality = {
  low: ["hb_hr:vanilla_fog_spawner_low"],
  medium: ["hb_hr:vanilla_fog_spawner_medium"],
  high: ["hb_hr:vanilla_fog_spawner_high"],
};

// VV variant for vanilla (currently empty = no particles)
const vvGeneralVanillaParticlesByQuality = {
  low: [],
  medium: [],
  high: [],
};

// Dynamic‐Property keys (base):
export const DP = {
  particleFog: "hb_hr:particleFog",
  ambientParticles: "hb_hr:ambientParticles",
  // tintedFog: "hb_hr:tintedFog",
  generalVanillaParticles: "hb_hr:generalVanillaParticles",
  renderQuality: "hb_hr:renderQuality",
  playerDimension: "hb_hr:playerDimension",
  lastBiome: "hb_hr:lastBiome",
  vibrantVisuals: "hb_hr:vibrant_visuals",
  // lastTintedFog: "hb_hr:lastTintedFog",
};

const QUALITY_OPTIONS = ["low", "medium", "high"];

// === BIOME LIST & DP HELPERS ===
const biomes = [
  { key: "default", name: "Vanilla", icon: "textures/hb/hr/ui/icon_vanilla" },
  { key: "red_moon", name: "Red Moon", icon: "textures/hb/hr/ui/icon_red_moon" },
  { key: "b1", name: "Dead Forest", icon: "textures/hb/hr/ui/icon_dead_forest" },
  { key: "b2", name: "Cursed Meadows", icon: "textures/hb/hr/ui/icon_cursed_meadows" },
  { key: "b3", name: "Black Forest", icon: "textures/hb/hr/ui/icon_black_forest" },
];

function biomePropKey(base, biome) {
  return `${base}_${biome}`;
}

function getBiomeSettings(player, biome) {
  return {
    particleFog: player.getDynamicProperty(biomePropKey(DP.particleFog, biome)) ?? true,
    ambientParticles: player.getDynamicProperty(biomePropKey(DP.ambientParticles, biome)) ?? true,
    renderQuality: player.getDynamicProperty(biomePropKey(DP.renderQuality, biome)) ?? "high",
    generalVanillaParticles: player.getDynamicProperty(DP.generalVanillaParticles) ?? true,
    vibrantVisuals: player.getDynamicProperty(DP.vibrantVisuals) ?? false,
  };
}

function setBiomeSettings(player, biome, s) {
  player.setDynamicProperty(biomePropKey(DP.particleFog, biome), s.particleFog);
  player.setDynamicProperty(biomePropKey(DP.ambientParticles, biome), s.ambientParticles);
  player.setDynamicProperty(biomePropKey(DP.renderQuality, biome), s.renderQuality);
  // generalVanillaParticles remains global
}

function openVibrantVisualsSettings(player) {
  const current = getVibrantVisuals(player);
  const options = ["hb_hr.vv_off_setting", "hb_hr.vv_on_setting"];
  // const options = ["OFF (more VFX)", "ON (less VFX)"];
  const defaultIndex = current ? 1 : 0;

  new ModalFormData()
    .title("hb_hr.vv_title")
    // .title("Vibrant visuals settings")
    .dropdown("hb_hr.vv_dropdown_text", options, defaultIndex)
    // .dropdown("\nFor better game VFX it is recommended to turn off vibrant visuals in your video settings AND set this setting to OFF.", options, defaultIndex)
    .submitButton("hb_hr.vv_save")
    // .submitButton("Save")
    .show(player)
    .then((res) => {
      if (!res || res.canceled) {
        openBiomeSelectionUI(player);
        return;
      }

      const [selectedIndex] = res.formValues;
      const enabled = selectedIndex === 1;

      setVibrantVisuals(player, enabled);

      // Build a message based on the selected state
      const stateText = enabled ? "hb_hr.vv_enabled" : "hb_hr.vv_disabled";
      // const stateText = enabled ? "ON" : "OFF";

      player.sendMessage({ translate: stateText });
      // player.sendMessage(`§eVibrant visuals are now: §6${stateText}§e.\n` + `§eMake sure your §6Vibrant Visuals§e video setting is also §c${stateText}§e in the game settings.`);

      openBiomeSelectionUI(player);
    });
}

function openBiomeSelectionUI(player) {
  const form = new ActionFormData().title("Choose Biome VFX");

  // First button: opens the separate vibrant visuals page
  form.button("Vibrant visuals settings");

  // Then all biome VFX buttons
  for (const biome of biomes) {
    form.button(biome.name, biome.icon);
  }

  form.show(player).then((response) => {
    if (!response || response.canceled) return;

    let index = -1;
    if (typeof response === "number") {
      index = response;
    } else if (typeof response.selection === "number") {
      index = response.selection;
    }

    if (index < 0) return;

    // index 0 = vibrant visuals settings
    if (index === 0) {
      openVibrantVisualsSettings(player);
      return;
    }

    // biome buttons start at index 1
    const biomeIndex = index - 1;
    if (biomeIndex < 0 || biomeIndex >= biomes.length) return;

    const biomeEntry = biomes[biomeIndex];
    openBiomeSettingsUI(player, biomeEntry.key, biomeEntry.name);
  });
}

function openBiomeChooser(player) {
  const form = new ActionFormData().title("Choose Biome VFX");

  for (const biome of biomes) {
    form.button(biome.name, biome.icon);
  }

  form.show(player).then((response) => {
    let index = -1;
    if (typeof response === "number") {
      index = response;
    } else if (response && typeof response.selection === "number") {
      index = response.selection;
    }

    if (index < 0 || index >= biomes.length) return;

    const biomeEntry = biomes[index];
    openBiomeSettingsUI(player, biomeEntry.key, biomeEntry.name);
  });
}

// === UI: Per‐biome settings ===
function openBiomeSettingsUI(player, biomeKey, biomeName) {
  const cur = getBiomeSettings(player, biomeKey);
  new ModalFormData()
    .title(`${biomeName} VFX Settings`)
    .toggle("Particle Fog", cur.particleFog)
    .toggle("Ambient Particles", cur.ambientParticles)
    .dropdown("Render Quality", QUALITY_OPTIONS, QUALITY_OPTIONS.indexOf(cur.renderQuality))
    .show(player)
    .then((res) => {
      if (res.canceled) return;
      const [pf, ap, rq] = res.formValues;
      const newSettings = {
        particleFog: !!pf,
        ambientParticles: !!ap,
        renderQuality: QUALITY_OPTIONS[typeof rq === "number" && rq >= 0 ? rq : QUALITY_OPTIONS.indexOf("high")],
      };

      // 1) save the new settings
      setBiomeSettings(player, biomeKey, newSettings);

      // 2) figure out “current biome” exactly as in the loop
      const raw = biomeCheck(player);
      const last = player.getDynamicProperty(DP.lastBiome) || "default";
      const curr = raw === null ? last : raw;

      // 3) if they just changed the fog toggle, run updateFogForPlayer
      //    (we pass curr and the freshly‐saved settings)
      updateFogForPlayer(player, curr, newSettings);
    });
}

// === BIOME & DIMENSION CHECKS ===
function isInOverWorldDimension(player) {
  return player.dimension.id === "minecraft:overworld";
}

function biomeCheck(player) {
  // special “red moon” override
  if (isRedMoon()) return "red_moon";
  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;
  }
  const timeOfDay = world.getTimeOfDay(); // 0 - 23999
  const isNight = timeOfDay >= 12500 && timeOfDay <= 23500;
  // real ground → map to biome (or vanilla)
  if (!blockToBiomeMap[id] && isNight) {
    return "default";
  } else {
    return blockToBiomeMap[id] || "none";
  }
}

// === FOG COMMAND HELPERS ===
function pushFog(player, fogId) {
  player.runCommand(`fog @s push ${fogId} ${fogId}`);
}
function popFog(player, fogId) {
  player.runCommand(`fog @s pop ${fogId}`);
}

// === PARTICLE SPAWNING ===
function triggerBiomeParticles(player, settings) {
  if (!settings.ambientParticles || !isInOverWorldDimension(player)) return;

  // const biome = biomeCheck(player);

  const biomeBase = biomeCheck(player);
  if (!biomeBase) return;

  const biome = resolveBiomeKeyForVv(player, biomeBase);

  if (!biome) return;

  const hit = player.dimension.getBlockFromRay(player.location, { x: 0, y: -1, z: 0 });
  if (!hit?.block) return;

  const pos = hit.block.center();

  // NEW: check global Vibrant Visuals DP
  const vibrant = getVibrantVisuals(player);

  // Decide which biome key to use in the map
  const vvKey = `vv_${biome}`;
  const source = (vibrant ? biomeEffectsByQuality[vvKey] : null) || biomeEffectsByQuality[biome] || biomeEffectsByQuality.default;

  const list = source[settings.renderQuality] || [];

  for (const pid of list) {
    try {
      player.spawnParticle(pid, { x: pos.x, y: pos.y + 1, z: pos.z });
    } catch (error) {}
  }
}

function triggerGeneralVanillaParticles(player, settings) {
  // respect the global toggle + dimension
  if (!settings.generalVanillaParticles || !isInOverWorldDimension(player)) return;

  // If Vibrant Visuals are enabled, we don't want vanilla particles.
  // You can later plug a `vv_vanilla` variant right here if needed.
  const vvEnabled = getVibrantVisuals(player);
  if (vvEnabled) {
    // Example for the future:
    for (const pid of vvGeneralVanillaParticlesByQuality[settings.renderQuality] || []) {
      const p = player.location;
      try {
        player.spawnParticle(pid, { x: p.x, y: p.y, z: p.z });
      } catch (error) {}
    }
    return;
  }

  // Normal vanilla particles when VV is OFF
  for (const pid of generalVanillaParticlesByQuality[settings.renderQuality] || []) {
    const p = player.location;
    try {
      player.spawnParticle(pid, { x: p.x, y: p.y, z: p.z });
    } catch (error) {}
  }
}

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

  // If biome didn't change, no need to touch fog
  if (currBiome === lastApplied) return;

  // Pop last fog (only if known)
  const lastFog = fogIds[lastApplied];
  if (lastFog) popFog(player, lastFog);

  // Push new fog
  const nextFog = fogIds[currBiome];
  if (nextFog) pushFog(player, nextFog);
  // world.sendMessage(nextFog);

  // persist
  player.setDynamicProperty(DP.lastBiome, currBiome);
}

// // === MUSIC LOGIC ===
// function playMusic(player, currBiome) {
//   const lastBiome = player.getDynamicProperty(DP.lastBiome) || "default";

//   // world.sendMessage("curr: " + currBiome);
//   // world.sendMessage("last: " + lastBiome);
//   // world.sendMessage("music: " + musicIds[currBiome]);
//   // 1) BIOME CHANGED
//   if (currBiome !== lastBiome) {
//     // stop any music
//     world.sendMessage("stop any music");
//     player.runCommand("/music stop 2");
//     if (musicIds[currBiome]) {
//       world.sendMessage("play new biome music");
//       player.sendMessage("/music play " + musicIds[currBiome] + " 1 2 loop");
//       player.runCommand("/music play " + musicIds[currBiome] + " 1 2 loop");
//     }
//     else{

//     }
//   }
// }
// // === SOUNDS LOGIC ===
function playSounds(player, currBiome, settings) {
  const lastBiome = player.getDynamicProperty(DP.lastBiome) || "default";

  // 1) SAME BIOME
  if (currBiome === lastBiome) {
    // pick sound list for this biome (fall back to default)
    const list = soundIds[currBiome] || soundIds.default;
    if (list.length > 0) {
      // choose one at random
      const idx = Math.floor(Math.random() * list.length);
      const sfx = list[idx];
      // play it on the player (you can tweak volume/pitch/falloff as needed)
      player.runCommand(`playsound ${sfx} @s ~ ~ ~ 1 1 1`);
    }
  }
}

// === MAIN LOOP & ITEM‐USE LISTENER ===
export function initVfxController() {
  system.runInterval(() => {
    for (const player of world.getAllPlayers()) {
      // 1) figure out raw biome (null means “keep last”)
      const raw = biomeCheck(player);
      const lastSaved = player.getDynamicProperty(DP.lastBiome) || "default";
      const baseBiome = raw === null ? lastSaved : raw;

      // Convert b1->vv_b1 if VV enabled (and variant exists)
      const currBiome = resolveBiomeKeyForVv(player, baseBiome);

      // playMusic(player, currBiome);
      const randomNoiseTick = Math.ceil(40 + Math.random() * 20);
      if (system.currentTick % randomNoiseTick === 0) playSounds(player, currBiome, getBiomeSettings(player, currBiome));

      // 2) special case: “none” → clear everything & skip
      if (currBiome === "none") {
        Object.values(fogIds).forEach((fid) => fid && popFog(player, fid));
        player.setDynamicProperty(DP.lastBiome, "none");
        // player.setDynamicProperty(DP.lastTintedFog, false);
        continue;
      }

      // 3) grab settings for this biome
      const settings = getBiomeSettings(player, currBiome);

      // ──────────── ADD THIS BLOCK ────────────
      // always force fog on in the banned_wither arena:
      if (currBiome === "banned_wither") {
        // settings.tintedFog = true;
      }
      // ─────────────────────────────────────────

      // 4) run unified fog logic (handles biome transitions + toggles)
      updateFogForPlayer(player, currBiome, settings);
      // 5) spawn particles if appropriate
      if (currBiome == "default") {
        if (system.currentTick % 60 === 0) triggerGeneralVanillaParticles(player, settings);
      } else {
        if (system.currentTick % 50 === 0) triggerBiomeParticles(player, settings);
      }
    }
  }, 1);

  // Item-use listener to open biome selection UI
  world.afterEvents.itemUse.subscribe((ev) => {
    const player = ev.source;
    const hand = player.getComponent("minecraft:equippable").getEquipment(EquipmentSlot.Mainhand);
    if (hand?.typeId === SETTINGS_ITEM) openBiomeSelectionUI(player);
  });
}

export function getVibrantVisuals(player) {
  return player.getDynamicProperty(DP.vibrantVisuals) ?? true;
}

function setVibrantVisuals(player, value) {
  player.setDynamicProperty(DP.vibrantVisuals, !!value);
}

function resolveBiomeKeyForVv(player, biomeKey) {
  const vvEnabled = getVibrantVisuals(player);
  if (!vvEnabled) return biomeKey;

  const vvKey = `vv_${biomeKey}`;
  return fogIds[vvKey] || biomeEffectsByQuality[vvKey] ? vvKey : biomeKey;
}
