import { system, world, GameMode } from "@minecraft/server";
import {
  neutralMobs,
  hostileMobs,
  evilMobs,
  goodMobs,
  villagers,
  xpValues,
  bossMobs,
  combinedMobs,
} from "../variables";
import { TIER1MAX, TIER2MAX, TIER3MAX, TIERPARAGONMAX } from "../constants";
export var goodXP = new Map();
export var checks = new Map();
export var goodTier = new Map();
export var goodXPChecks = new Map();
export var reverseGoodXPChecks = new Map();

// Checks if the player is good; if not, don't run
export function isDisabled(player) {
  return (
    player.hasTag("good") ||
    player.hasTag("neutral") ||
    player.getGameMode() == GameMode.creative ||
    player.getGameMode() == GameMode.spectator
  );
}

// Initializes the player's data from tags
export function initializePlayerData(player) {
  try {
    const tags = player.getTags();
    let xpTag = null;
    let tierTag = null;

    // Search for relevant tags
    for (const tag of tags) {
      if (tag.startsWith("goodXP_")) {
        xpTag = tag;
      } else if (tag.startsWith("good_tier_")) {
        tierTag = tag;
      }
    }

    // Restore XP from the tag or default to 0
    if (xpTag) {
      const xp = parseInt(xpTag.split("_")[1], 10);
      goodXP.set(player.id, xp);
    } else if (!goodXP.has(player.id)) {
      goodXP.set(player.id, 0); // Only set default if no prior value exists
    }

    // Restore Tier from the tag or default to 1
    if (tierTag) {
      const playerTier = parseInt(tierTag.split("_")[2], 10);
      goodTier.set(player.id, playerTier);
    } else if (!goodTier.has(player.id)) {
      goodTier.set(player.id, 1); // Only set default if no prior value exists
    }
  } catch (error) {
    console.error(`Error initializing player data: ${error}`);
  }
}

// Updates the player's tags to store XP and tier
export function updatePlayerTags(player) {
  const xp = goodXP.get(player.id) || 0;
  const playerTier = goodTier.get(player.id) || 1;

  // Remove old tags
  player.getTags().forEach((tag) => {
    if (tag.startsWith("goodXP_") || tag.startsWith("good_tier_")) {
      player.removeTag(tag);
    }
  });

  // Add updated tags
  player.addTag(`goodXP_${xp}`);
  player.addTag(`good_tier_${playerTier}`);
}

export function upgradePlayerTier(player) {
  if (!player) return;
  let currentTier = goodTier.get(player.id) || 1;
  let playerGoodXP = goodXP.get(player.id) || 0;
  if (currentTier >= 3) {
    console.error(`§cYou have already reached the maximum tier.`);
    return;
  }
  currentTier += 1;
  playerGoodXP = 0;

  goodTier.set(player.id, currentTier);
  goodXP.set(player.id, playerGoodXP);
  player.runCommand(`playsound float_ad.level_up_good "${player.name}"`);

  updatePlayerTags(player);
  player.removeTag(`check_item_good_${currentTier}_helmet`);
  if (currentTier < 3) {
    player.addTag(`check_item_good_${currentTier + 1}_helmet`);
  }
}

// Clears tracking checks
export function clearTrackCheck(playerId) {
  const checkId = goodXPChecks.get(playerId);
  if (checkId !== undefined) {
    checks.delete(checkId);
    goodXPChecks.delete(playerId);
    reverseGoodXPChecks.delete(checkId);
  }
}

// Updates player's progress and tags
export function progress(player, amount) {
  if (player !== undefined) {
    // Retrieve the goodXP value from the player's tag
    const tags = player.getTags();
    let tagXP = 0;

    for (const tag of tags) {
      if (tag.startsWith("goodXP_")) {
        tagXP = parseInt(tag.split("_")[1], 10) || 0;
        break;
      }
    }

    // Use the tagXP value to update the goodXP map
    goodXP.set(player.id, tagXP);

    let playergoodXP = goodXP.get(player.id) || 0;
    let currentTier = goodTier.get(player.id) || 1;

    // Calculate the maxXP based on the current tier
    let maxXP;
    if (currentTier == 1) maxXP = TIER1MAX;
    else if (currentTier == 2) maxXP = TIER2MAX;
    else if (currentTier == 3) maxXP = TIER3MAX;
    else maxXP = TIERPARAGONMAX;

    // Ensure XP does not go below 0 and prevent tier downgrade
    if (amount < 0 && playergoodXP + amount < 0) {
      amount = -playergoodXP;
    }

    // Update the XP and handle level-ups
    playergoodXP = Math.max(0, playergoodXP + amount);
    if (currentTier == 3) {
      return;
    }
    if (playergoodXP >= maxXP) {
      playergoodXP = maxXP;
      player.sendMessage(
        "§aYou have reached the maximum level for this tier." +
          "§r\n§aYou can now upgrade to the next tier." +
          "§r\n§aCraft the next tier Laurel at the hub."
      );

      // Play level up sound based on affiliation
      if (player.hasTag("good")) {
        player.runCommand(`playsound float_ad.level_up_good "${player.name}"`);
      } else if (player.hasTag("evil")) {
        player.runCommand(`playsound float_ad.level_up_evil "${player.name}"`);
      }

      //upgradePlayerTier(player);
    }

    // Update the maps and tags
    goodXP.set(player.id, playergoodXP);
    updatePlayerTags(player);
    displayGoodXP(player, playergoodXP);
  }
}

// Displays the Good XP bar
export function displayGoodXP(player, level) {
  try {
    //updatePlayerTags(player);
    let currentTier = goodTier.get(player.id) || 1;
    let maxXP;
    if (currentTier == 1) maxXP = TIER1MAX;
    else if (currentTier == 2) maxXP = TIER2MAX;
    else if (currentTier == 3) maxXP = TIER3MAX;
    else maxXP = TIER3MAX;

    const progress = Math.min(level / maxXP, 1);

    const totalSquares = 30;
    const filledSquares = Math.round(progress * totalSquares);
    const emptySquares = totalSquares - filledSquares;

    const xpBar = `§a${"⬛".repeat(filledSquares)}§7${"⬜".repeat(emptySquares)}`;
    if (currentTier == 3) {
      player.onScreenDisplay.setActionBar(`§l§2Good XP§r\n§aCurrent Max Angel Tier`);
    } else {
      player.onScreenDisplay.setActionBar(`§l§2Good XP§r\n${xpBar}\n§rAmount: ${level}/${maxXP}`);
    }
  } catch (error) {
    console.error(`Error displaying XP bar: ${error}`);
  }
}

// Handles XP changes when a mob is killed
export function mobKilled(mob, location, player, deadEntity) {
  if (!combinedMobs.includes(mob)) {
    return; // Do nothing if the mob is not in the combinedMobs list
  }

  let amount = xpValues[mob];
  let isGain = false;

  if (mob === "float_ad:wisp" || mob === "float_ad:elemental_golem") {
    const state = deadEntity.getProperty("float_ad:state");
    amount = xpValues[mob];
    if (state == 2) {
      isGain = true;
    } else if (state == 1) {
      isGain = false;
    } else {
      amount = 0;
    }
  } else {
    isGain = hostileMobs.includes(mob) || evilMobs.includes(mob) || bossMobs.includes(mob);
  }

  if (amount !== 0) {
    const particleEffect = isGain ? `xp_gain_${Math.abs(amount)}` : `xp_drain_${Math.abs(amount)}`;
    player.runCommand(`particle float_ad:${particleEffect} ${location.x} ${location.y} ${location.z}`);
    progress(player, isGain ? amount : -amount);
  }
}
