import { system, world, ItemStack, EquipmentSlot } from "@minecraft/server";

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

  constructor() {
    this.initialize();
  }

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

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

    system.afterEvents.scriptEventReceive.subscribe((event) => {
      if (event.sourceEntity == undefined) return;
      else {
        if (event.sourceEntity.typeId.includes("hb_cb:mini_jukebox_on_player")) {
          let allTags = event.sourceEntity.getTags();
          const allPlayers = world.getAllPlayers();
          switch (event.id) {
            case "hb_cb:start_on_player":
              allPlayers.forEach((player) => {
                const playerMiniJukeboxTag = "hb_cb_" + player.id;
                if (playerMiniJukeboxTag == allTags[0]) {
                  player.runCommand("/playsound hb_cb:" + event.message + " @s");
                }
              });
              break;
            case "hb_cb:stop_on_player":
              allPlayers.forEach((player) => {
                const playerMiniJukeboxTag = "hb_cb_" + player.id;
                if (playerMiniJukeboxTag == allTags[0]) {
                  player.runCommand("/stopsound @s hb_cb:" + event.message);
                }
              });
              break;

            default:
              break;
          }
        }
      }
    });

    world.afterEvents.playerSpawn.subscribe((event) => {
      const playerMiniJukeboxTag = "hb_cb_" + event.player.id;
      // // world.sendMessage("/event entity @e[type=hb_cb:mini_jukebox_on_player,tag=" + playerMiniJukeboxTag + "] hb_cb:despawn");
      event.player.runCommand("/event entity @e[type=hb_cb:mini_jukebox_on_player,tag=" + playerMiniJukeboxTag + "] hb_cb: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) + 16,
        z: event.player.location.z,
      };
      const allMiniJukeboxs = event.player.dimension.getEntities({ type: "hb_cb:mini_jukebox_on_player", tags: [playerMiniJukeboxTag] });
      try {
        if (allMiniJukeboxs.length > 1) {
          allMiniJukeboxs.forEach((miniJukebox) => {
            if (!miniJukebox.isValid()) return;
            miniJukebox.remove();
          });
        }
        if (allMiniJukeboxs.length > 0 || !allMiniJukeboxs) {
          allMiniJukeboxs.forEach((miniJukebox) => {
            if (!miniJukebox.isValid()) return;
            miniJukebox.teleport(loc);
            miniJukebox.applyImpulse(velocity);
          });
        } else {
          let newMiniJukebox = event.player.dimension.spawnEntity("hb_cb:mini_jukebox_on_player", loc);
          newMiniJukebox.addTag(playerMiniJukeboxTag);
        }
      } catch (error) {}
    });

    system.runInterval(() => {
      try {
        if (curTick > INIT_TIME) {
          const allPlayers = world.getAllPlayers();
          allPlayers.forEach((player) => {
            if (!player.isValid()) return;
            this.handleMiniJukeboxDisplay(player, curTick);
            this.handleMiniJukeboxParticles(player, curTick);
          });
        }
        curTick++;
      } catch (e) {
        console.warn(e);
      }
    }, 0);
  }

  handleMiniJukeboxDisplay(player, curTick) {
    const playerMiniJukeboxTag = "hb_cb_" + player.id;
    let velocity = player.getVelocity();
    let loc = {
      x: player.location.x,
      y: player.location.y + (player.isSneaking ? 1.3 : 1.6) + 16,
      z: player.location.z,
    };
    const allMiniJukeboxs = player.dimension.getEntities({ type: "hb_cb:mini_jukebox_on_player", tags: [playerMiniJukeboxTag] });
    try {
      if (allMiniJukeboxs.length > 1) {
        allMiniJukeboxs.forEach((miniJukebox) => {
          if (!miniJukebox.isValid()) return;
          miniJukebox.remove();
        });
      }
      if (allMiniJukeboxs.length > 0) {
        allMiniJukeboxs.forEach((miniJukebox) => {
          if (!miniJukebox.isValid()) return;
          // // // world.sendMessage("counter: " + miniJukebox.getProperty("hb_cb:slot_counter"));
          miniJukebox.teleport(loc);
          miniJukebox.applyImpulse(velocity);
          testPlayState(miniJukebox, player);
        });
      } else {
        // world.sendMessage("SPAWNNNN HERE ###########");
        let newMiniJukebox = player.dimension.spawnEntity("hb_cb:mini_jukebox_on_player", loc);
        newMiniJukebox.addTag(playerMiniJukeboxTag);
      }
    } catch (error) {}
  }
  handleMiniJukeboxParticles(player, curTick) {
    if (curTick % 20 != 0) return;
    const playerMiniJukeboxTag = "hb_cb_" + player.id;
    let loc = {
      x: player.location.x,
      y: player.location.y + (player.isSneaking ? 1.3 : 1.6) + 16,
      z: player.location.z,
    };
    const allMiniJukeboxs = player.dimension.getEntities({ type: "hb_cb:mini_jukebox_on_player", tags: [playerMiniJukeboxTag] });
    try {
      if (allMiniJukeboxs.length > 1) {
        allMiniJukeboxs.forEach((miniJukebox) => {
          if (!miniJukebox.isValid()) return;
          miniJukebox.remove();
        });
      }
      if (allMiniJukeboxs.length > 0) {
        allMiniJukeboxs.forEach((miniJukebox) => {
          if (!miniJukebox.isValid()) return;
          const slot_counter = miniJukebox.getProperty("hb_cb:slot_counter");
          if (slot_counter != 0) {
            try {
              player.dimension.spawnParticle("hb_cb:mini_jukebox", {
                x: player.location.x,
                y: player.location.y + (player.isSneaking ? 0.7 : 1),
                z: player.location.z,
              });
            } catch (error) {}
          }
        });
      } else {
      }
    } catch (error) {}
  }
}

function testPlayState(miniJukebox, player) {
  const slot_counter = miniJukebox.getProperty("hb_cb:slot_counter");
  let armorItem = player.getComponent("equippable").getEquipment(EquipmentSlot.Chest);
  if (!armorItem) {
    // no backpack is equipped
    // // world.sendMessage("no item is equipped");
    if (slot_counter != 0) {
      turnOffMiniJukeBox(miniJukebox);
      // // world.sendMessage("stop all if sounds are being played and set discs to 0");
      return;
      // stop all if sounds are being played and set discs to 0
    }
  }
  if (armorItem.typeId.includes("hb_cb:") && armorItem.typeId.includes("_bp_") && armorItem.typeId.includes("mini_jukebox")) {
    // backpack with jukebox armor item is equipped
    // // world.sendMessage("backpack with jukebox armor item is equipped");
    // // world.sendMessage(slot_counter.toString());
    checkForSlotChanges(miniJukebox, armorItem);
    // // world.sendMessage(slot_counter.toString());
    if (slot_counter == 0) {
      for (let i = 0; i <= 4; i++) {
        const propKey = `hb_cb:slot_${i}_disc`;

        const armorItemValue = armorItem.getDynamicProperty(propKey) ?? 0;

        if (armorItemValue != 0) {
          // // world.sendMessage("set new slot here");
          // i +1 because 0 is the off state and the states 1 to 5 are the slots for the discs
          if (miniJukebox.isValid()) miniJukebox.setProperty("hb_cb:slot_counter", i + 1);
        }
      }
      // // world.sendMessage("start new sopunds=");
    }
  } else if (armorItem.typeId.includes("hb_cb:") && armorItem.typeId.includes("_bp_") && !armorItem.typeId.includes("mini_jukebox")) {
    // backpack WITHOUT jukebox armor item is equipped
    // // world.sendMessage("backpack WITHOUT jukebox armor item is equipped");
    if (slot_counter != 0) {
      turnOffMiniJukeBox(miniJukebox);
      // // world.sendMessage("stop all if sounds are being played and set discs to 0");
      return;
      // stop all if sounds are being played and set discs to 0
    }
  } else {
    // no backpack is equipped
    // // world.sendMessage("no backpack is equipped");
    if (slot_counter != 0) {
      turnOffMiniJukeBox(miniJukebox);
      // // world.sendMessage("stop all if sounds are being played and set discs to 0");
      return;
      // stop all if sounds are being played and set discs to 0
    }
  }
}

function turnOffMiniJukeBox(miniJukebox) {
  if (miniJukebox.isValid()) miniJukebox.setProperty("hb_cb:slot_counter", 0);
  if (miniJukebox.isValid()) miniJukebox.setProperty("hb_cb:slot_0_disc", 0);
  if (miniJukebox.isValid()) miniJukebox.setProperty("hb_cb:slot_1_disc", 0);
  if (miniJukebox.isValid()) miniJukebox.setProperty("hb_cb:slot_2_disc", 0);
  if (miniJukebox.isValid()) miniJukebox.setProperty("hb_cb:slot_3_disc", 0);
  if (miniJukebox.isValid()) miniJukebox.setProperty("hb_cb:slot_4_disc", 0);
}

function checkForSlotChanges(miniJukebox, armorItem) {
  // Check slots 0 through 4
  for (let i = 0; i <= 4; i++) {
    const propKey = `hb_cb:slot_${i}_disc`;

    // dynamic (in‑game) vs. stored property
    const armorItemValue = armorItem.getDynamicProperty(propKey) ?? 0;
    const entityValue = miniJukebox.getProperty(propKey) ?? 0;

    if (armorItemValue !== entityValue) {
      // record the change
      if (miniJukebox.isValid()) miniJukebox.setProperty(propKey, 0);
      system.runTimeout(() => {
        if (miniJukebox.isValid()) miniJukebox.setProperty(propKey, armorItemValue);
      }, 5);
    }
  }
}

// ("/scriptevent hb_cb:start_on_player no_disc");
// ("/scriptevent hb_cb:start_on_player disc_11");
// ("/scriptevent hb_cb:start_on_player disc_13");
// ("/scriptevent hb_cb:start_on_player disc_5");
// ("/scriptevent hb_cb:start_on_player disc_blocks");
// ("/scriptevent hb_cb:start_on_player disc_cat");
// ("/scriptevent hb_cb:start_on_player disc_chirp");
// ("/scriptevent hb_cb:start_on_player disc_creator");
// ("/scriptevent hb_cb:start_on_player disc_creator_music_box");
// ("/scriptevent hb_cb:start_on_player disc_far");
// ("/scriptevent hb_cb:start_on_player disc_mall");
// ("/scriptevent hb_cb:start_on_player disc_mellohi");
// ("/scriptevent hb_cb:start_on_player disc_otherside");
// ("/scriptevent hb_cb:start_on_player disc_pigstep_master");
// ("/scriptevent hb_cb:start_on_player disc_precipice");
// ("/scriptevent hb_cb:start_on_player disc_relic");
// ("/scriptevent hb_cb:start_on_player disc_stal");
// ("/scriptevent hb_cb:start_on_player disc_strad");
// ("/scriptevent hb_cb:start_on_player disc_tears");
// ("/scriptevent hb_cb:start_on_player disc_wait");
// ("/scriptevent hb_cb:start_on_player disc_ward");
