import { system, world } from '@minecraft/server';
system.runInterval(() => {
  for (const player of world.getAllPlayers()) {
    if (Math.random() < 0.4) {
      player.playSound("ambient", { volume: 0.2, pitch: 1 })
    }
  }
}, 1000)
const musicDiscs = new Map([["kick:record_15", "§6Record 15"]]);

let playingJukeboxes = new Map();
let lastestPlayingPosition = new Map();

const DYNAMIC_PROPERTY_ID = "jukebox_states";

let soundParticle = new Map();

function saveJukeboxStates() {
  const dataToSave = Array.from(playingJukeboxes.entries());
  const jsonString = JSON.stringify(dataToSave);
  world.setDynamicProperty(DYNAMIC_PROPERTY_ID, jsonString);
}

function loadJukeboxStates() {
  const jsonString = world.getDynamicProperty(DYNAMIC_PROPERTY_ID);
  if (typeof jsonString === 'string') {
    const loadedData = JSON.parse(jsonString);
    playingJukeboxes.clear();
    for (const [locationKey, recordId] of loadedData) {
      playingJukeboxes.set(locationKey, recordId);
    }
  }
}

system.run(loadJukeboxStates);

function stopSound(player, locationKey) {
  system.run(function () {
    if (playingJukeboxes.has(locationKey)) {
      const soundId = playingJukeboxes.get(locationKey);

      if (lastestPlayingPosition.has(soundId)) {
        const lastestPosition = lastestPlayingPosition.get(soundId);
        if (lastestPosition === locationKey) {
          lastestPlayingPosition.delete(soundId);
          player.runCommand(`stopsound @a ${soundId}`);
        }
      }
    }

    playingJukeboxes.delete(locationKey);
    if (soundParticle.has(locationKey)) {
      const intervalCommand = soundParticle.get(locationKey);
      system.clearRun(intervalCommand);
    }
    saveJukeboxStates();
  });
}

world.beforeEvents.playerInteractWithBlock.subscribe(evd => {
  const { player, itemStack, block } = evd;
  const { x, y, z } = block.location;
  const locationKey = `${x},${y},${z}`;

  if (!block.permutation.matches('minecraft:jukebox')) return;

  if (playingJukeboxes.has(locationKey)) {
    stopSound(player, locationKey);
    return;
  }

  if (itemStack) {
    if (musicDiscs.has(itemStack.typeId)) {
      system.run(function () {
        const soundId = `record.${itemStack.typeId.replace(':', '_')}`;

        playingJukeboxes.set(locationKey, soundId);
        saveJukeboxStates();

        player.runCommand(`title @a[r=10] actionbar §dNow playing: ${musicDiscs.get(itemStack.typeId)}`);

        const soundParticleCommand = system.runInterval(() => {
          player.runCommand(`particle minecraft:note_particle ${x} ${y + 1.2} ${z}`);
        }, 20);

        soundParticle.set(locationKey, soundParticleCommand);
        lastestPlayingPosition.set(soundId, locationKey);
        const silenceInterval = system.runInterval(() => {
          player.dimension.runCommand("stopsound @a music");
          player.dimension.runCommand("stopsound @a ambient");
          player.dimension.runCommand("stopsound @a weather");
        }, 2);
        player.runCommand(`playsound ${soundId} @a`)
        system.runTimeout(() => {
          system.clearRun(silenceInterval)
        }, 1860)
      });
      return;
    } else if (itemStack.hasTag("minecraft:music_disc")) {
      playingJukeboxes.set(locationKey, itemStack.typeId);
      saveJukeboxStates();
      return;
    }
  }
});

world.beforeEvents.playerBreakBlock.subscribe((event) => {
  const { player, block } = event;
  const { x, y, z } = block.location;
  const locationKey = `${x},${y},${z}`;

  if (playingJukeboxes.has(locationKey)) {
    stopSound(player, locationKey);
    return;
  }
})
system.runInterval(() => {
  for (const player of world.getPlayers()) {
    const nearby = player.dimension.getEntities({
      type: "kick:wendigo_stalker",
      location: player.location,
      maxDistance: 20
    });

    const hasNearby = nearby.length > 0;
    if (!player.soundPlaying && hasNearby) {
      player.playSound("heartbeat", { volume: 1, pitch: 1 })
      player.soundPlaying = true;
    }

    if (player.soundPlaying && !hasNearby) {
      player.runCommand(`stopsound @s`);
      player.soundPlaying = false;
    }
  }
}, 20);
const soundState = new Map();

system.runInterval(() => {
  const overworld = world.getDimension("overworld");

  for (const player of world.getPlayers()) {
    let foundNearby = false;
    const pl = player.location;

    for (let x = -8; x <= 8 && !foundNearby; x++) {
      for (let y = -8; y <= 8 && !foundNearby; y++) {
        for (let z = -8; z <= 8 && !foundNearby; z++) {
          const block = overworld.getBlock({
            x: Math.floor(pl.x + x),
            y: Math.floor(pl.y + y),
            z: Math.floor(pl.z + z)
          });
          if (block && block.typeId === "kick:wendigo_heart") {
            foundNearby = true;
          }
        }
      }
    }

    let cooldown = soundState.get(player.id) ?? 0;

    if (foundNearby) {
      if (cooldown <= 0) {
        player.runCommand(`playsound whisper @s`);
        soundState.set(player.id, 40);
      } else {
        soundState.set(player.id, cooldown - 1);
      }
    } else {
      if (soundState.has(player.id)) {
        player.runCommand(`stopsound @s`);
        soundState.delete(player.id);
      }
    }
  }
}, 50);
system.afterEvents.scriptEventReceive.subscribe((yti) => {
  if (yti.id === "sai:rick") {
    for (const player of world.getAllPlayers()) {
      player.addTag("wither")
    }
  }
})
system.runInterval(() => {
  for (const player of world.getAllPlayers()) {
    if (player.hasTag("wither")) {
      player.removeTag("wither")
      system.runTimeout(() => {
        player.runCommand('event entity @e[type=kick:wendigo_die] kick:wither')
        system.runTimeout(() => {
          player.runCommand('tp @e[type=kick:wendigo_die] ~ -500 ~')
        }, 48000)
      }, 48000)
    }
  }
}, 20)

