import { world, system, ItemStack } from "@minecraft/server";
import { hatsToCheck, hatDisplayNames, shortHandHats, reverseShortHandHats } from "./juststuff.js";
import { openHolidayChanceForm, openLegendaryChanceForm, openHatSpawnChanceForm, openResetSessionStatsForm } from './spawnConfigUI.js';
import { getFormattedDateTime } from "./holidays.js";
import { ActionFormData } from "@minecraft/server-ui";

const UNLOCKED_HATS_PROP = "unlockedHats";
const SESSION_STATS_PROP = "sessionStats";
const PERMANENT_STATS_PROP = "permanentStats";
const GLOBAL_PLAYERS_LIST_PROP = "globalPlayerList";

const TRACKED_SLOTS = ["Head", "Chest", "Legs", "Feet", "Offhand"];
const POSITION_THRESHOLD = 0.01;

const playerLastPositions = new Map();

if (world.getDynamicProperty("worldStartTick") === undefined) {
  world.setDynamicProperty("worldStartTick", system.currentTick);
}

const STAT_KEYS = ["equippedTimes", "killCounts", "damageDealt", "damageTaken", "blocksBroken", "blocksPlaced", "distanceTraveled"];

//pack items
function packItemStats(statsObj) {
  return STAT_KEYS.map(key => {
    let value = statsObj[key] ?? 0;
    if (key === "damageDealt" || key === "damageTaken" || key === "distanceTraveled") {
      value = Math.round(value * 10) / 10;
    }
    if (key === "equippedTimes") {
      value = Math.floor(value / 20); // compress to seconds
    }
    return value;
  }).join("|");
}
//unpackitems
function unpackItemStats(packedString) {
  const values = packedString.split("|").map(Number);
  const obj = {};
  STAT_KEYS.forEach((key, i) => {
    let value = values[i] ?? 0;
    if (key === "equippedTimes") {
      value = value * 20; // decompress back to ticks
    }
    obj[key] = value;
  });
  return obj;
}
function getWorldDay() {
  const startTick = world.getDynamicProperty("worldStartTick") ?? 0;
  return Math.floor((system.currentTick - startTick) / 24000) + 1;
}
//packprimary
function packPrimaryTotals(statsObj) {
  return STAT_KEYS.map(key => {
    let value = statsObj[key] ?? 0;
    if (key === "damageDealt" || key === "damageTaken" || key === "distanceTraveled") {
      value = Math.round(value * 10) / 10;
    }
    if (key === "equippedTimes") {
      value = Math.floor(value / 20); // ticks to seconds
    }
    return value;
  }).join("|");
}
//unpackprimary
function unpackPrimaryTotals(packedString) {
  const values = packedString.split("|").map(Number);
  const obj = {};
  STAT_KEYS.forEach((key, i) => {
    let value = values[i] ?? 0;
    if (key === "equippedTimes") {
      value = value * 20; // decompress seconds to ticks
    }
    obj[key] = value;
  });
  return obj;
}

function loadGlobalPlayerList() {
  const data = world.getDynamicProperty(GLOBAL_PLAYERS_LIST_PROP);
  if (typeof data != "string") return undefined;
  try {
    let returnValue = JSON.parse(`{"value":${data}}`);
    return returnValue.value;
  } catch {
    return undefined;
  }
}

function saveGlobalPlayerList(list) {
  world.setDynamicProperty(GLOBAL_PLAYERS_LIST_PROP, JSON.stringify(list));
}

function addPlayerToGlobalList(playerName) {
  let list = loadGlobalPlayerList() ?? [];
  if (!list.includes(playerName)) {
    list.push(playerName);
    saveGlobalPlayerList(list);
  }
}
//load offline players totals
function loadOfflinePrimaryTotals(playerName) {
  const packed = world.getDynamicProperty(`primaryTotals_${playerName}`);
  if (!packed || typeof packed !== "string") return createEmptyStats().primaryTotals;

  try {
    return unpackPrimaryTotals(packed);
  } catch {
    return createEmptyStats().primaryTotals;
  }
}

function loadSavedPermanentStats(playerName) {
  const packed = world.getDynamicProperty(`primaryTotals_${playerName}`);
  if (!packed || typeof packed !== "string") return null;
  try {
    return {
      primaryTotals: unpackPrimaryTotals(packed),
    };
  } catch {
    return null;
  }
}
//
// --- Unlock system ---
//

function loadUnlockedHats(player) {
  const data = player.getDynamicProperty(UNLOCKED_HATS_PROP);
  if (!data || typeof data !== "string") return createEmptyUnlockStats();

  const unlockSet = new Set();
  const unlockTimes = {};
  const unlockDates = {};

  const entries = data.split(";");
  for (const entry of entries) {
    const [short, timeStr, dateStr] = entry.split("|");
    const full = reverseShortHandHats[short] || short;
    unlockSet.add(full);
    if (timeStr) unlockTimes[full] = Number(timeStr);
    if (dateStr) unlockDates[full] = dateStr;
  }

  return {
    unlockSet,
    unlockTimes,
    unlockDates,
  };
}

function createEmptyUnlockStats() {
  return {
    unlockSet: new Set(),
    unlockTimes: {},
    unlockDates: {},
  };
}

function saveUnlockedHats(player, stats) {
  const packed = Array.from(stats.unlockSet).map(id => {
    const short = shortHandHats[id] || id;
    const time = stats.unlockTimes[id] ?? "";
    const date = stats.unlockDates[id] ?? "";
    return `${short}|${time}|${date}`;
  }).join(";");

  player.setDynamicProperty(UNLOCKED_HATS_PROP, packed);
}

function createEmptyStats() {
  return {
    equippedTimes: {},
    currentlyEquipped: {},
    killCounts: {},
    damageDealt: {},
    damageTaken: {},
    blocksBroken: {},
    blocksPlaced: {},
    distanceTraveled: {},
    primaryTotals: {
      equippedTimes: 0,
      killCounts: 0,
      damageDealt: 0,
      damageTaken: 0,
      blocksBroken: 0,
      blocksPlaced: 0,
      distanceTraveled: 0,
    },
    lastPrimaryItemId: undefined, 
  };
}

function loadSessionStats(player) {
  const data = player.getDynamicProperty(SESSION_STATS_PROP);
  const stats = createEmptyStats();

  if (!data) return stats;

  try {
    const raw = JSON.parse(data);

    // Restore stat blocks
    for (const [shortId, packed] of Object.entries(raw.statBlocks ?? {})) {
      const fullId = reverseShortHandHats[shortId] || shortId;
      const unpacked = unpackItemStats(packed);
      for (const key of STAT_KEYS) {
        stats[key][fullId] = unpacked[key];
      }
    }

    // Restore additional state
    stats.currentlyEquipped = raw.currentlyEquipped ?? {};
    stats.lastPrimaryItemId = raw.lastPrimaryItemId ?? undefined;
stats.primaryTotals = {
  equippedTimes: raw.primaryTotals?.equippedTimes ?? 0,
  killCounts: raw.primaryTotals?.killCounts ?? 0,
  damageDealt: raw.primaryTotals?.damageDealt ?? 0,
  damageTaken: raw.primaryTotals?.damageTaken ?? 0,
  blocksBroken: raw.primaryTotals?.blocksBroken ?? 0,
  blocksPlaced: raw.primaryTotals?.blocksPlaced ?? 0,
  distanceTraveled: raw.primaryTotals?.distanceTraveled ?? 0,
};

  } catch (e) {
    console.warn("Failed to load session stats:", e);
    return createEmptyStats();
  }

  return stats;
}


function loadPermanentStats(player) {
  const data = player.getDynamicProperty(PERMANENT_STATS_PROP);
  const stats = createEmptyStats();

  if (!data) return stats;

  try {
    const raw = JSON.parse(data);

    for (const [shortId, packed] of Object.entries(raw)) {
      if (shortId === "__primaryTotals") continue; // handle separately below

      const fullId = reverseShortHandHats[shortId] || shortId;
      const unpacked = unpackItemStats(packed);
      for (const key of STAT_KEYS) {
        stats[key][fullId] = unpacked[key];
      }
    }

    // ✅ Restore primaryTotals if present
    if (raw.__primaryTotals) {
      stats.primaryTotals = raw.__primaryTotals;
    }

  } catch {
    return createEmptyStats();
  }

  return stats;
}
function resetSessionStatsForAllPlayers() {
  for (const player of world.getPlayers()) {
    player.setDynamicProperty(PERMANENT_STATS_PROP, JSON.stringify(createEmptyStats()));
  }
}

function saveSessionStats(player, stats) {
  if (!stats) stats = createEmptyStats();

  const packed = {
    statBlocks: {},
    currentlyEquipped: stats.currentlyEquipped,
    lastPrimaryItemId: stats.lastPrimaryItemId,
    primaryTotals: stats.primaryTotals,
  };

  const allItemIds = new Set();

  for (const key of STAT_KEYS) {
    if (!stats[key]) continue;
    for (const itemId of Object.keys(stats[key])) {
      allItemIds.add(itemId);
    }
  }

  for (const itemId of allItemIds) {
    const short = shortHandHats[itemId] || itemId;
    const statBlock = {};
    for (const key of STAT_KEYS) {
      statBlock[key] = stats[key]?.[itemId] ?? 0;
    }
    const combined = packItemStats(statBlock);
    if (combined !== "0|0|0|0|0|0|0") {
      packed.statBlocks[short] = combined;
    }
  }

  player.setDynamicProperty(SESSION_STATS_PROP, JSON.stringify(packed));
}


function savePermanentStats(player, stats) {
  if (!stats) stats = createEmptyStats();

  const packed = {};
  const allItemIds = new Set();

  for (const key of STAT_KEYS) {
    if (!stats[key]) continue;
    for (const itemId of Object.keys(stats[key])) {
      allItemIds.add(itemId);
    }
  }

  for (const itemId of allItemIds) {
    const short = shortHandHats[itemId] || itemId;
    const statBlock = {};
    for (const key of STAT_KEYS) {
      statBlock[key] = stats[key]?.[itemId] ?? 0;
    }
    const combined = packItemStats(statBlock);
    if (combined !== "0|0|0|0|0|0|0") {
      packed[short] = combined;
    }
  }

  // ✅ Add primaryTotals as a separate object (not compressed)
  packed["__primaryTotals"] = stats.primaryTotals;
const packedPrimaryTotals = packPrimaryTotals(stats.primaryTotals);
world.setDynamicProperty(`primaryTotals_${player.name}`, packedPrimaryTotals);
  player.setDynamicProperty(PERMANENT_STATS_PROP, JSON.stringify(packed));
}
function getEquippedItems(player) {
  const equipment = player.getComponent("minecraft:equippable");
  if (!equipment) return [];
  return TRACKED_SLOTS.map(slot => {
    const item = equipment.getEquipment(slot);
    if (item && item.typeId.startsWith("just:")) {
      return { slot, itemId: item.typeId };
    }
    return null;
  }).filter(Boolean);
}

function getPrimaryEquippedHat(stats) {
  for (const slot of TRACKED_SLOTS) {
    const entry = stats.currentlyEquipped[slot];
    if (entry && entry.itemId.startsWith("just:")) {
      return { itemId: entry.itemId, slot };
    }
  }
  return null;
}
//
// --- Update Equipped Time & Unlock Hats ---
//

function updateEquippedTimeAndUnlock(player) {
  let unlockStats = loadUnlockedHats(player);
  let sessionStats = loadSessionStats(player);
  let permanentStats = loadPermanentStats(player);
  const currentTick = system.currentTick;
  const equippedItems = getEquippedItems(player);

  for (const slot of TRACKED_SLOTS) {
    const equipped = equippedItems.find(e => e.slot === slot);

    if (equipped) {
      const { itemId } = equipped;

const shortId = shortHandHats[itemId] || itemId;
const fullId = reverseShortHandHats[shortId] || shortId; // This will be itemId in most cases
if (!unlockStats.unlockSet.has(fullId)) {
  unlockStats.unlockSet.add(fullId);
  unlockStats.unlockTimes[fullId] = getWorldDay();
  unlockStats.unlockDates[fullId] = getFormattedDateTime();
  const displayName = hatDisplayNames[itemId] || itemId;
  player.sendMessage(`You have unlocked the Cosmetic: ${displayName} on ${unlockStats.unlockDates[fullId]}`);
  //ADDON BOOK
  // Check if this is the first hat unlocked and give the book
if (!player.getDynamicProperty("hasReceivedAddonBook")) {
  if (unlockStats.unlockSet.size === 1) {
   const bookItem = new ItemStack("just:addon_book", 1);
   player.getComponent("inventory")?.container?.addItem(bookItem);
    player.setDynamicProperty("hasReceivedAddonBook", true);
  }
}
}
      const currentEquip = sessionStats.currentlyEquipped[slot];
      if (!currentEquip || currentEquip?.itemId !== itemId) {
        sessionStats.currentlyEquipped[slot] = { itemId, startTick: currentTick };
      } else {
        const elapsedTicks = currentTick - currentEquip.startTick;
        sessionStats.equippedTimes[itemId] = (sessionStats.equippedTimes[itemId] ?? 0) + elapsedTicks;
        sessionStats.currentlyEquipped[slot].startTick = currentTick;
      }
    } else if (sessionStats.currentlyEquipped[slot]) {
      const prev = sessionStats.currentlyEquipped[slot];
      const elapsedTicks = currentTick - prev.startTick;
      sessionStats.equippedTimes[prev?.itemId] = (sessionStats.equippedTimes[prev?.itemId] ?? 0) + elapsedTicks;
      permanentStats.equippedTimes[prev?.itemId] = (permanentStats.equippedTimes[prev?.itemId] ?? 0) + elapsedTicks;
      delete sessionStats.currentlyEquipped[slot];
    }
  }

  const primaryEquipment = getPrimaryEquippedHat(sessionStats);
  const primaryId = primaryEquipment?.itemId ?? undefined;

  // *** Detect primary hat change and save ***
if (sessionStats.lastPrimaryItemId && sessionStats.lastPrimaryItemId !== primaryId) {
  const lastId = sessionStats.lastPrimaryItemId;

  // Merge into permanent stats
  for (const key of STAT_KEYS) {
    const value = sessionStats[key]?.[lastId] ?? 0;
    permanentStats[key][lastId] = (permanentStats[key][lastId] ?? 0) + value;
  }

  for (const key of Object.keys(sessionStats.primaryTotals)) {
    permanentStats.primaryTotals[key] += sessionStats.primaryTotals[key] ?? 0;
  }

  // Clear session stats for previous primary
  for (const key of STAT_KEYS) {
    delete sessionStats[key][lastId];
  }

  sessionStats.primaryTotals = {
    equippedTimes: 0,
    killCounts: 0,
    damageDealt: 0,
    damageTaken: 0,
    blocksBroken: 0,
    blocksPlaced: 0,
    distanceTraveled: 0,
  };
}

  // Update lastPrimaryItemId to the current primary
  sessionStats.lastPrimaryItemId = primaryId;

  if (primaryId) {
    if (!sessionStats.currentlyEquipped["__primary"] || sessionStats.currentlyEquipped["__primary"]?.itemId !== primaryId) {
      sessionStats.currentlyEquipped["__primary"] = { itemId: primaryId, startTick: currentTick };
    } else {
      const elapsed = currentTick - sessionStats.currentlyEquipped["__primary"].startTick;
      sessionStats.primaryTotals.equippedTimes += elapsed;

      sessionStats.currentlyEquipped["__primary"].startTick = currentTick;

      // Update primaryTotals with current cumulative stats
      sessionStats.primaryTotals.equippedTimes = sessionStats.equippedTimes[primaryId] ?? 0;
      sessionStats.primaryTotals.killCounts = sessionStats.killCounts[primaryId] ?? 0;
      sessionStats.primaryTotals.damageDealt = sessionStats.damageDealt[primaryId] ?? 0;
      sessionStats.primaryTotals.damageTaken = sessionStats.damageTaken[primaryId] ?? 0;
      sessionStats.primaryTotals.blocksBroken = sessionStats.blocksBroken[primaryId] ?? 0;
      sessionStats.primaryTotals.blocksPlaced = sessionStats.blocksPlaced[primaryId] ?? 0;
      sessionStats.primaryTotals.distanceTraveled = sessionStats.distanceTraveled[primaryId] ?? 0;
    }
  } else if (sessionStats.currentlyEquipped["__primary"]) {
    const prev = sessionStats.currentlyEquipped["__primary"];
    const elapsed = currentTick - prev.startTick;

    sessionStats.equippedTimes[prev?.itemId] = (sessionStats.equippedTimes[prev?.itemId] ?? 0) + elapsed;
    sessionStats.primaryTotals.equippedTimes += elapsed;

    delete sessionStats.currentlyEquipped["__primary"];
  }

  saveUnlockedHats(player, unlockStats);
  saveSessionStats(player, sessionStats);
  savePermanentStats(player, permanentStats);
}
//
// --- Distance Tracking ---
//

function updateDistanceTraveled(player) {
  let sessionStats = loadSessionStats(player);
  let permanentStats = loadPermanentStats(player);
  const location = player.location;
  if (!playerLastPositions.has(player)) {
    playerLastPositions.set(player, { x: location.x, z: location.z });
    return;
  }

  const lastPos = playerLastPositions.get(player);
  const dx = location.x - lastPos.x;
  const dz = location.z - lastPos.z;
  const dist = Math.sqrt(dx * dx + dz * dz);

  if (dist > POSITION_THRESHOLD) {
    const counted = new Set();
    let primaryContributed = false;

    for (const slot of TRACKED_SLOTS.concat(["__primary"])) {
      const entry = sessionStats.currentlyEquipped[slot];
      if (entry && !counted.has(entry?.itemId)) {
        sessionStats.distanceTraveled[entry?.itemId] = (sessionStats.distanceTraveled[entry?.itemId] ?? 0) + dist;
        counted.add(entry?.itemId);

        if (slot === "__primary" && !primaryContributed) {
          sessionStats.primaryTotals.distanceTraveled += dist;
          primaryContributed = true;
        }
      }
    }
    playerLastPositions.set(player, { x: location.x, z: location.z });
  }

  saveSessionStats(player, sessionStats);
  savePermanentStats(player, permanentStats);
}

function updateStatForEquippedItems(player, statKey, incrementValue) {
  const counted = new Set();
  let primaryContributed = false;
  let sessionStats = loadSessionStats(player);
  let permanentStats = loadPermanentStats(player);
  for (const slot of TRACKED_SLOTS.concat(["__primary"])) {
    const entry = sessionStats.currentlyEquipped[slot];
    if (entry && !counted.has(entry?.itemId)) {
      sessionStats[statKey][entry?.itemId] = (sessionStats[statKey][entry?.itemId] ?? 0) + incrementValue;
      permanentStats[statKey][entry?.itemId] = (permanentStats[statKey][entry?.itemId] ?? 0) + incrementValue;
      counted.add(entry?.itemId);
      if (slot === "__primary" && !primaryContributed) {
        sessionStats.primaryTotals[statKey] += incrementValue;
        permanentStats.primaryTotals[statKey] += incrementValue;
        primaryContributed = true;
      }
    }
  }
  saveSessionStats(player, sessionStats);
}

//
// --- Event handlers for Stats. ---
//

world.afterEvents.entityHurt.subscribe(event => {
  const source = event.damageSource?.damagingEntity;
  const hurtEntity = event.hurtEntity;
//damage dealt
  if (source?.typeId === "minecraft:player") {
    updateStatForEquippedItems(source, "damageDealt", event.damage);
  }
//damage taken
  if (hurtEntity?.typeId === "minecraft:player") {
    updateStatForEquippedItems(hurtEntity, "damageTaken", event.damage);
  }
});

world.afterEvents.entityDie.subscribe(event => {
  const source = event.damageSource?.damagingEntity;
  if (!source || source.typeId !== "minecraft:player") return;
  updateStatForEquippedItems(source, "killCounts", 1);
});

world.afterEvents.playerBreakBlock.subscribe(event => {
  const player = event.player;
  if (!player) return;
  updateStatForEquippedItems(player, "blocksBroken", 1);
});

world.afterEvents.playerPlaceBlock.subscribe(event => {
  const player = event.player;
  if (!player) return;
  updateStatForEquippedItems(player, "blocksPlaced", 1);
});

// Periodic update
system.runInterval(() => {
  for (const player of world.getPlayers()) {
    addPlayerToGlobalList(player.name);
    updateEquippedTimeAndUnlock(player);
    updateDistanceTraveled(player);
  }
}, 20);

world.beforeEvents.playerLeave.subscribe(data => {
  updateTotalStats(data.player, true);
});

//
// --- Periodic tick update for time and distance tracking ---
//

function updateTotalStats(player, save = false) {
  const sessionStats = loadSessionStats(player);
  const permanentStats = loadPermanentStats(player);
  const newPermanentStats = permanentStats;

  function addStatSafe(container, key, value) {
    container[key] = (container[key] ?? 0) + Number(value ?? 0);
  }

  for (const [id, stat] of Object.entries(sessionStats.killCounts)) {
    addStatSafe(newPermanentStats.killCounts, id, stat);
    newPermanentStats.totalKillCount += Number(stat) ?? 0;
  }

  for (const [id, stat] of Object.entries(sessionStats.damageDealt)) {
    addStatSafe(newPermanentStats.damageDealt, id, stat);
    newPermanentStats.totalDamageDealt += Number(stat) ?? 0;
  }

  for (const [id, stat] of Object.entries(sessionStats.equippedTimes)) {
    addStatSafe(newPermanentStats.equippedTimes, id, stat);
    newPermanentStats.totalEquippedTimes += Number(stat) ?? 0;
  }

  for (const [id, stat] of Object.entries(sessionStats.blocksBroken)) {
    addStatSafe(newPermanentStats.blocksBroken, id, stat);
    newPermanentStats.totalBlocksBroken += Number(stat) ?? 0;
  }

  for (const [id, stat] of Object.entries(sessionStats.blocksPlaced)) {
    addStatSafe(newPermanentStats.blocksPlaced, id, stat);
    newPermanentStats.totalBlocksPlaced += Number(stat) ?? 0;
  }

  for (const [id, stat] of Object.entries (sessionStats.distanceTraveled)) {
    addStatSafe(newPermanentStats.distanceTraveled, id, stat);
    newPermanentStats.totalDistanceTraveled += Number(stat) ?? 0;
  }

  for (const [id, stat] of Object.entries(sessionStats.damageTaken)) {
    addStatSafe(newPermanentStats.damageTaken, id, stat);
    newPermanentStats.totalDamageTaken += Number(stat) ?? 0;
  }

  if (save) {
    const sessionTotal = updatePrimaryTotal(player, true);
    newPermanentStats.primaryTotals.equippedTimes += sessionTotal.primaryTotals.equippedTimes;
    newPermanentStats.primaryTotals.killCounts += sessionTotal.primaryTotals.killCounts;
    newPermanentStats.primaryTotals.damageDealt += sessionTotal.primaryTotals.damageDealt;
    newPermanentStats.primaryTotals.damageTaken += sessionTotal.primaryTotals.damageTaken;
    newPermanentStats.primaryTotals.blocksBroken += sessionTotal.primaryTotals.blocksBroken;
    newPermanentStats.primaryTotals.blocksPlaced += sessionTotal.primaryTotals.blocksPlaced;
    newPermanentStats.primaryTotals.distanceTraveled += sessionTotal.primaryTotals.distanceTraveled;

    savePermanentStats(player, newPermanentStats);
    saveSessionStats(player, undefined);
  }

  return newPermanentStats;
}

function updatePrimaryTotal(player, save = true) {
  let sessionStats = loadSessionStats(player);
  let primaryItemId = sessionStats.lastPrimaryItemId;
  let newSessionStats = sessionStats;

  newSessionStats.primaryTotals.equippedTimes = sessionStats.equippedTimes[primaryItemId] ?? 0;
  newSessionStats.primaryTotals.killCounts = sessionStats.killCounts[primaryItemId] ?? 0;
  newSessionStats.primaryTotals.damageDealt = sessionStats.damageDealt[primaryItemId] ?? 0;
  newSessionStats.primaryTotals.damageTaken = sessionStats.damageTaken[primaryItemId] ?? 0;
  newSessionStats.primaryTotals.blocksBroken = sessionStats.blocksBroken[primaryItemId] ?? 0;
  newSessionStats.primaryTotals.blocksPlaced = sessionStats.blocksPlaced[primaryItemId] ?? 0;
  newSessionStats.primaryTotals.distanceTraveled = sessionStats.distanceTraveled[primaryItemId] ?? 0;

  if (save) {
    saveSessionStats(player, newSessionStats);
  }

  return newSessionStats;
}



////////////////////////////////////////////////////////////////////////////////

const CATEGORY_ICONS = {
  "Cosmetics Collection": "textures/items/duck_hat",
  "How it works": "textures/items/addon_book",
  "Other": "textures/ui/world_glyph_color",
  "Other Addons": "textures/ui/sidebar_icons/addon",
  "Settings": "textures/ui/settings_icon",
  "Customization Options": "textures/ui/dressing_room_customization"
};

const SUBCATEGORY_ICONS = {
  "§8Common A - M": "textures/items/hatbag_common",
  "§8Common N - Z": "textures/items/hatbag_common",
  "§eUnCommon A - M": "textures/items/hatbag_uncommon",
  "§eUnCommon N - Z": "textures/items/hatbag_uncommon",
  "§bRare A - M": "textures/items/hatbag_rare",
  "§bRare N - Z": "textures/items/hatbag_rare",
  "§5Epic A - M": "textures/items/hatbag_epic",
  "§5Epic N - Z": "textures/items/hatbag_epic",
  "§dEaster": "textures/items/hatbag_easter",
  "§6Summer": "textures/items/hatbag_summer",
  "§uHalloween": "textures/items/hatbag_halloween",
  "§4Festive": "textures/items/hatbag_festive",
  "§gLegendary": "textures/items/hatscraps_legendary",
  "§mOther Addons Required": "textures/ui/sidebar_icons/addon",
  "§3Shirts A-M": "textures/items/crop_top",
  "§3Shirts N-Z": "textures/items/t_shirt",
  "§3Pants A-M": "textures/items/camo_pants",
  "§3Pants N-Z": "textures/items/slacks",
    "§3Shoes": "textures/items/sneakers",
  "§3Accessories": "textures/items/just_large_eyes",
  "§8Cosmetics Tables": "textures/ui/press",
  "§8Obtaining Cosmetics": "textures/items/duck_hat",
  "§8Scraps": "textures/items/hatscraps_common",
  "§8Displays": "textures/items/hat_display",
  "§8Cosmetics Mechanics": "textures/ui/armor_full",
  "§8Changelog": "textures/ui/book_addtextpage_default",
  "§8Collaborations": "textures/ui/sidebar_icons/dressing_room_skins",
  "§8Settings": "textures/ui/settings_glyph_color_2x",
  "§8Stats": "textures/ui/trophy",
  "§8Eye Height": "textures/ui/subcategory_icons/eyes",
  "§8Body Size": "textures/ui/subcategory_icons/body_size",
  "§8Credit": "textures/items/book_writable"


};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////


class CustomForm {
  data = new Map();
  titleText = "";
  bodytext = "";

  title(title) {
    this.titleText = title;
    return this;
  }

  body(txt) {
    this.bodytext = txt;
    return this;
  }

  button(category, subcategory, text, texture = "", enchanted = false, description = "", itemId = "") {
    if (!this.data.has(category)) {
      this.data.set(category, new Map());
    }

    const subMap = this.data.get(category);
    if (!subMap.has(subcategory)) {
      subMap.set(subcategory, []);
    }

    const itemData = {
      text,
      texture,
      enchanted,
      description,
    };

    if (category === "Cosmetics Collection" && itemId) {
      itemData.itemId = itemId;
    }

    subMap.get(subcategory).push(itemData);
    return this;
  }

  async showCategoryMenu(player) {
    const form = new ActionFormData();
    form.title(this.titleText);
    form.body(this.bodytext);

    const categories = Array.from(this.data.keys());
    for (const category of categories) {
      const icon = CATEGORY_ICONS[category];
      form.button(category, icon ?? "");
    }

    const response = await form.show(player);
    if (!response || response.canceled) return;

    const selectedCategory = categories[response.selection];
    return this.showSubcategoryMenu(player, selectedCategory);
  }

  async showSubcategoryMenu(player, category) {
    const form = new ActionFormData();
    form.title(`§8${category}`);
    form.body("Choose a subcategory");

    const subMap = this.data.get(category);
    const subcategories = Array.from(subMap.keys());

    for (const subcategory of subcategories) {
      const icon = SUBCATEGORY_ICONS[subcategory];
      form.button(subcategory, icon ?? "");
    }

    form.button("§8⬅ Back");
    form.button("§c⤴ Home");

    const response = await form.show(player);
    if (!response || response.canceled) return;

    if (response.selection === subcategories.length) {
      return this.showCategoryMenu(player);
    }
    if (response.selection === subcategories.length + 1) {
      return this.showCategoryMenu(player);
    }

    const selectedSubcategory = subcategories[response.selection];
    return this.showItemMenu(player, category, selectedSubcategory);
  }

  async showItemMenu(player, category, subcategory) {
    const form = new ActionFormData();
    form.title(`${category} > ${subcategory}`);
    form.body("Choose an item");

    const items = this.data.get(category).get(subcategory);
    const { unlockSet, unlockTimes } = loadUnlockedHats(player);

    for (const item of items) {
      let isUnlocked = true;
      let displayText = `§8${item.text}\n`;

      if (category === "Cosmetics Collection") {
        isUnlocked = item?.itemId ? unlockSet.has(item?.itemId) : true;

        if (isUnlocked) {
          displayText += `§8Unlocked on Day §l${unlockTimes[item?.itemId] || "Unknown"}`;
        } else {
          displayText = `§7${item.text}\n §4(Locked)§r`;
        }
      }

      form.button(displayText, item.texture || "");
    }

    form.button("§8⬅ Back");
    form.button("§c⤴ Home");

    const response = await form.show(player);
    if (!response || response.canceled) return;

    if (response.selection === items.length) {
      return this.showSubcategoryMenu(player, category);
    }
    if (response.selection === items.length + 1) {
      return this.showCategoryMenu(player);
    }

    const selectedItem = items[response.selection];

    if (category === "Cosmetics Collection" && selectedItem?.itemId) {
      if (!unlockSet.has(selectedItem?.itemId)) {
        player.sendMessage("This item is locked.");
        return this.showItemMenu(player, category, subcategory);
      }
    }
    if (selectedItem.text === "Cosmetic Bag Chance") {
      const tags = player.getTags();
      if (!tags.includes("justop")) {
        player.sendMessage("§cYou do not have permission to access Configure Drop Chances.\nUse Command:\n\n /tag @s add justop \n\nto gain access.");
        return this.showItemMenu(player, category, subcategory);
      }
      await openHolidayChanceForm(player);
      return this.showCategoryMenu(player);
    }
    if (selectedItem.text === "Legendary Bag Chance") {
      const tags = player.getTags();
      if (!tags.includes("justop")) {
        player.sendMessage("§cYou do not have permission to access Configure Drop Chances.\nUse Command:\n\n /tag @s add justop \n\nto gain access.");
        return this.showItemMenu(player, category, subcategory);
      }
      await openLegendaryChanceForm(player);
      return this.showCategoryMenu(player);
    }
    if (selectedItem.text === "Mobs with Hats Spawn Chance") {
      const tags = player.getTags();
      if (!tags.includes("justop")) {
        player.sendMessage("§cYou do not have permission to access Configure Drop Chances.\nUse Command:\n\n /tag @s add justop \n\nto gain access.");
        return this.showItemMenu(player, category, subcategory);
      }
      await openHatSpawnChanceForm(player);
      return this.showCategoryMenu(player);
    }
    if (selectedItem.text === "Reset Stats") {
      const tags = player.getTags();
      if (!tags.includes("justop")) {
        player.sendMessage("§cYou do not have permission to reset session stats.\nUse Command:\n\n /tag @s add justop \n\nto gain access.");
        return this.showItemMenu(player, category, subcategory);
      }
      await openResetSessionStatsForm(player);
      return this.showCategoryMenu(player);
    }
    return this.showDetail(player, selectedItem, category, subcategory);
  }

  async showDetail(player, item, category, subcategory) {
    const form = new ActionFormData();
    form.title(item.text);

    let fullDescription = item.description || "No description available.";

    //// Handle "Cosmetics" category and "cosmetics" item
if (category === "Cosmetics Collection" && item?.itemId) {
  //player.sendMessage(`DEBUG: Using itemId: ${item?.itemId}`);
const unlockStats = loadUnlockedHats(player);
const permanentStats = loadPermanentStats(player);

const unlockTime = unlockStats.unlockTimes[item?.itemId];
const unlockDate = unlockStats.unlockDates[item?.itemId];
      ///R///
const sessionStats = loadSessionStats(player);

const kills = (permanentStats.killCounts?.[item?.itemId] ?? 0) + (sessionStats.killCounts?.[item?.itemId] ?? 0);
const dealt = (permanentStats.damageDealt?.[item?.itemId] ?? 0) + (sessionStats.damageDealt?.[item?.itemId] ?? 0);
const taken = (permanentStats.damageTaken?.[item?.itemId] ?? 0) + (sessionStats.damageTaken?.[item?.itemId] ?? 0);
const broken = (permanentStats.blocksBroken?.[item?.itemId] ?? 0) + (sessionStats.blocksBroken?.[item?.itemId] ?? 0);
const placed = (permanentStats.blocksPlaced?.[item?.itemId] ?? 0) + (sessionStats.blocksPlaced?.[item?.itemId] ?? 0);
const distance = Math.round((permanentStats.distanceTraveled?.[item?.itemId] ?? 0) + (sessionStats.distanceTraveled?.[item?.itemId] ?? 0));

const TICKS_PER_SECOND = 20;
const totalTicks = (permanentStats.equippedTimes?.[item?.itemId] ?? 0) + (sessionStats.equippedTimes?.[item?.itemId] ?? 0);
const totalSeconds = Math.floor(totalTicks / TICKS_PER_SECOND);
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;

let timeFormatted = "";
if (days > 0) timeFormatted += `${days}d `;
if (hours > 0 || days > 0) timeFormatted += `${hours}h `;
if (minutes > 0 || hours > 0 || days > 0) timeFormatted += `${minutes}m `;
timeFormatted += `${seconds}s`;

      if (unlockTime || unlockDate) {
        fullDescription +=
`\n\n§2§l==========================§r
\n\n§f§lUnlocked on§r:
§6In-game Day: §f${unlockTime ?? "Unknown"}
§6Real Time: §f${unlockDate ?? "Unknown"}
§6Total Equipped Time: §f${timeFormatted}
§f§lCOMBAT§r
§6Total Kills: §f${Math.floor(kills)}
§6Damage Taken: §f${taken.toFixed(1)}
§6Damage Dealt: §f${dealt.toFixed(1)}
§f§lBLOCKS§r
§6Blocks Broken: §f${Math.floor(broken)}
§6Blocks Placed: §f${Math.floor(placed)}
§6Distance Traveled: §f${distance} blocks`;
      }
    }
    // Handle "Other" category and "Personal Stats" item
    else if (category === "Other" && item.text === "Personal Stats") {

      function formatTicksToTime(ticks) {
        const totalSeconds = Math.floor(ticks / 20);
        const d = Math.floor(totalSeconds / 86400);
        const h = Math.floor((totalSeconds % 86400) / 3600);
        const m = Math.floor((totalSeconds % 3600) / 60);
        const s = totalSeconds % 60;
        return `${d > 0 ? d + "d " : ""}${h > 0 ? h + "h " : ""}${m > 0 ? m + "m " : ""}${s}s`;
      }

      function getMostWornHat(equippedTimes = {}) {
        let maxTime = 0;
        let mostWornHatId = null;
        for (const [itemId, time] of Object.entries(equippedTimes)) {
          if (time > maxTime) {
            maxTime = time;
            mostWornHatId = itemId;
          }
        }
        return { mostWornHatId, maxTime };
      }


      function buildPersonalStatsUI(player, hatDisplayNames = {}) {
        let permanentStats = updateTotalStats(player, true);
        let newPrimaryStats = permanentStats.primaryTotals
        const sessionStats = loadSessionStats(player);

        newPrimaryStats.equippedTimes += sessionStats.primaryTotals.equippedTimes
        newPrimaryStats.killCounts += sessionStats.primaryTotals.killCounts
        newPrimaryStats.damageDealt += sessionStats.primaryTotals.damageDealt
        newPrimaryStats.damageTaken += sessionStats.primaryTotals.damageTaken
        newPrimaryStats.blocksBroken += sessionStats.primaryTotals.blocksBroken
        newPrimaryStats.blocksPlaced += sessionStats.primaryTotals.blocksPlaced
        newPrimaryStats.distanceTraveled += sessionStats.primaryTotals.distanceTraveled

        const totals = newPrimaryStats || {
          equippedTimes: 0,
          killCounts: 0,
          damageDealt: 0,
          damageTaken: 0,
          blocksBroken: 0,
          blocksPlaced: 0,
          distanceTraveled: 0,
        };

        const { mostWornHatId, maxTime: mostWornTime } = getMostWornHat(permanentStats.equippedTimes || {});
        const mostWornTimeFormatted = formatTicksToTime(mostWornTime ?? 0);

        return `
§f§lCOMBAT§r
§6Total Kills: §f${Math.floor(totals.killCounts)}
§6Damage Dealt: §f${totals.damageDealt.toFixed(1)}
§6Damage Taken: §f${totals.damageTaken.toFixed(1)}

§f§lBLOCKS§r
§6Blocks Broken: §f${Math.floor(totals.blocksBroken)}
§6Blocks Placed: §f${Math.floor(totals.blocksPlaced)}

§f§lMOVEMENT§r
§6Distance Traveled: §f${Math.round(totals.distanceTraveled)} blocks

§f§lTIME EQUIPPED§r
§6Total Equipped Time: §f${formatTicksToTime(totals.equippedTimes ?? 0)}

§f§lMOST WORN COSMETIC§r
§6Cosmetic: §f${mostWornHatId ? (hatDisplayNames[mostWornHatId] || mostWornHatId) : "None"}
§6Time Worn: §f${mostWornHatId ? mostWornTimeFormatted : "0s"}
`.trim();
      };

      // Assign final string
      fullDescription = buildPersonalStatsUI(player, hatDisplayNames);
    }
    //LEADERBOARD
    else if (category === "Other" && item.text === "Leaderboard") {
      function formatTicksToTime(ticks) {
        const totalSeconds = Math.floor(ticks / 20);
        const d = Math.floor(totalSeconds / 86400);
        const h = Math.floor((totalSeconds % 86400) / 3600);
        const m = Math.floor((totalSeconds % 3600) / 60);
        const s = totalSeconds % 60;
        return `${d > 0 ? d + "d " : ""}${h > 0 ? h + "h " : ""}${m > 0 ? m + "m " : ""}${s}s`;
      }



function gatherAllPlayersPrimaryPermanentStats() {
  let allStats = [];
  let playerNames = loadGlobalPlayerList();
  if (playerNames.length < 1) return allStats;

  const onlinePlayers = world.getPlayers();
  const onlinePlayerMap = new Map(onlinePlayers.map(p => [p.name, p]));

  for (let name of playerNames) {
    const isOnline = onlinePlayerMap.has(name);
    const player = onlinePlayerMap.get(name);

    // Load saved permanent stats from dynamic property
    let permanentStats = loadSavedPermanentStats(name); // << You need to implement this if not already
    if (!permanentStats) continue;

    let newPrimaryStats = permanentStats.primaryTotals || {
      equippedTimes: 0,
      killCounts: 0,
      damageDealt: 0,
      damageTaken: 0,
      blocksBroken: 0,
      blocksPlaced: 0,
      distanceTraveled: 0,
    };

    // If player is online, merge in session stats (but do NOT overwrite saved ones)
    if (isOnline) {
      const sessionStats = loadSessionStats(player);
      newPrimaryStats = {
        equippedTimes: newPrimaryStats.equippedTimes + (sessionStats.primaryTotals.equippedTimes ?? 0),
        killCounts: newPrimaryStats.killCounts + (sessionStats.primaryTotals.killCounts ?? 0),
        damageDealt: newPrimaryStats.damageDealt + (sessionStats.primaryTotals.damageDealt ?? 0),
        damageTaken: newPrimaryStats.damageTaken + (sessionStats.primaryTotals.damageTaken ?? 0),
        blocksBroken: newPrimaryStats.blocksBroken + (sessionStats.primaryTotals.blocksBroken ?? 0),
        blocksPlaced: newPrimaryStats.blocksPlaced + (sessionStats.primaryTotals.blocksPlaced ?? 0),
        distanceTraveled: newPrimaryStats.distanceTraveled + (sessionStats.primaryTotals.distanceTraveled ?? 0),
      };
    }

    allStats.push({ playerName: name, stats: newPrimaryStats });
  }

  return allStats;
}

      function getTopPlayersByStat(allStats, statKey, topCount = 5) {
        return allStats
          .filter(p => p.stats[statKey] > 0)
          .sort((a, b) => b.stats[statKey] - a.stats[statKey])
          .slice(0, topCount);
      }

      function formatLeaderboard(title, allStats, statKey, isTime = false, isDistance = false) {
        const topPlayers = getTopPlayersByStat(allStats, statKey);
        let result = `§f§l${title.toUpperCase()}§r\n`;
        if (topPlayers.length === 0) {
          result += "§7No data available.\n";
        } else {
          topPlayers.forEach(({ playerName, stats }, i) => {
            let value = stats[statKey];
            if (isTime) value = formatTicksToTime(value);
            else if (isDistance) value = `${Math.round(value)} blocks`;
            else value = Math.round(value);
            result += `${i + 1}. §6${playerName}§r - §e${value}\n`;
          });
        }
        return result;
      }

      function getFullPrimaryPermanentLeaderboard() {
        const allStats = gatherAllPlayersPrimaryPermanentStats();
        return [
          formatLeaderboard("Top Kills", allStats, "killCounts"),
          formatLeaderboard("Top Damage Dealt", allStats, "damageDealt"),
          formatLeaderboard("Top Damage Taken", allStats, "damageTaken"),
          formatLeaderboard("Top Blocks Broken", allStats, "blocksBroken"),
          formatLeaderboard("Top Blocks Placed", allStats, "blocksPlaced"),
          formatLeaderboard("Top Equipped Time", allStats, "equippedTimes", true),
          formatLeaderboard("Top Distance Traveled", allStats, "distanceTraveled", false, true),
        ].join("\n\n");
      }
      // Assign to your description variable here
      fullDescription = getFullPrimaryPermanentLeaderboard();
    }



    // Handle "Other" category and Resettable "Session Leaderboard" 
    else if (category === "Other" && item.text === "Session Leaderboard") {
      /*function loadGlobalPlayerList() {
        const data = world.getDynamicProperty("globalPlayerList");
        if (!data) return [];
        try {
          return JSON.parse(data);
        } catch {
          return [];
        }
      }*/

      function getPrimaryStats(player) {
        const sessionStats = loadSessionStats(player);
        const primaryId = sessionStats.currentlyEquipped?.["__primary"]?.itemId;

        if (!primaryId) {
          return {
            itemId: null,
            session: {
              equippedTimes: 0,
              killCounts: 0,
              damageDealt: 0,
              damageTaken: 0,
              blocksBroken: 0,
              blocksPlaced: 0,
              distanceTraveled: 0,
            }
          };
        }

        return {
          itemId: primaryId,
          session: {
            equippedTimes: sessionStats.equippedTimes?.[primaryId] ?? 0,
            killCounts: sessionStats.killCounts?.[primaryId] ?? 0,
            damageDealt: sessionStats.damageDealt?.[primaryId] ?? 0,
            damageTaken: sessionStats.damageTaken?.[primaryId] ?? 0,
            blocksBroken: sessionStats.blocksBroken?.[primaryId] ?? 0,
            blocksPlaced: sessionStats.blocksPlaced?.[primaryId] ?? 0,
            distanceTraveled: sessionStats.distanceTraveled?.[primaryId] ?? 0,
          }
        };
      }

      function gatherPrimarySessionStats() {
        let allStats = [];
        const playerNames = loadGlobalPlayerList();

        for (const name of playerNames) {
          const player = world.getPlayers().find(p => p.name === name);
          if (!player) continue;

          const { session } = getPrimaryStats(player);
          allStats.push({ playerName: name, stats: session });
        }

        return allStats;
      }

      function getTop(allStats, key, isTime = false, isDistance = false) {
        const sorted = allStats
          .map(p => ({ playerName: p.playerName, value: p.stats[key] ?? 0 }))
          .sort((a, b) => b.value - a.value)
          .slice(0, 5);

        return sorted.map((entry, i) => {
          const val = isTime
            ? formatTicksToTime(entry.value)
            : isDistance
              ? `${Math.round(entry.value)} blocks`
              : Math.round(entry.value);
          return `${i + 1}. §6${entry.playerName}§r - §e${val}`;
        }).join("\n");
      }

      function formatTicksToTime(ticks) {
        const totalSeconds = Math.floor(ticks / 20);
        const d = Math.floor(totalSeconds / 86400);
        const h = Math.floor((totalSeconds % 86400) / 3600);
        const m = Math.floor((totalSeconds % 3600) / 60);
        const s = totalSeconds % 60;
        return `${d > 0 ? d + "d " : ""}${h > 0 ? h + "h " : ""}${m > 0 ? m + "m " : ""}${s}s`;
      }

      const all = gatherPrimarySessionStats();

      fullDescription =
        `§f§lTop Kills (Primary Only)§r\n${getTop(all, "killCounts")}\n\n` +
        `§f§lTop Damage Dealt (Primary Only)§r\n${getTop(all, "damageDealt")}\n\n` +
        `§f§lTop Damage Taken (Primary Only)§r\n${getTop(all, "damageTaken")}\n\n` +
        `§f§lTop Blocks Broken (Primary Only)§r\n${getTop(all, "blocksBroken")}\n\n` +
        `§f§lTop Blocks Placed (Primary Only)§r\n${getTop(all, "blocksPlaced")}\n\n` +
        `§f§lTop Equipped Time (Primary Only)§r\n${getTop(all, "equippedTimes", true)}\n\n` +
        `§f§lTop Distance Traveled (Primary Only)§r\n${getTop(all, "distanceTraveled", false, true)}\n\n`;
    }

    ////GLOBAL STAT MENU
    else if (category === "Other" && item.text === "Global Stats") {
      /*function loadGlobalPlayerList() {
        const data = world.getDynamicProperty("globalPlayerList");
        if (!data) return [];
        try {
          return JSON.parse(data);
        } catch {
          return [];
        }
      }*/

      /*function loadPermanentStats(player) {
        const data = player.getDynamicProperty("permanentStats");
        if (!data) return {};
        try {
          return JSON.parse(data);
        } catch {
          return {};
        }
      }*/

  function formatTicksToTime(ticks) {
    const totalSeconds = Math.floor(ticks / 20);
    const d = Math.floor(totalSeconds / 86400);
    const h = Math.floor((totalSeconds % 86400) / 3600);
    const m = Math.floor((totalSeconds % 3600) / 60);
    const s = totalSeconds % 60;
    return `${d > 0 ? d + "d " : ""}${h > 0 ? h + "h " : ""}${m > 0 ? m + "m " : ""}${s}s`;
  }

  const globalTotals = {
    totalKills: 0,
    totalDamageDealt: 0,
    totalDamageTaken: 0,
    totalBlocksBroken: 0,
    totalBlocksPlaced: 0,
    totalDistanceTraveled: 0,
    totalEquippedTimes: 0,
  };

  for (const name of loadGlobalPlayerList()) {
    const saved = loadSavedPermanentStats(name);
    if (!saved) continue;

    const totals = saved.primaryTotals;

    globalTotals.totalKills += totals.killCounts ?? 0;
    globalTotals.totalDamageDealt += totals.damageDealt ?? 0;
    globalTotals.totalDamageTaken += totals.damageTaken ?? 0;
    globalTotals.totalBlocksBroken += totals.blocksBroken ?? 0;
    globalTotals.totalBlocksPlaced += totals.blocksPlaced ?? 0;
    globalTotals.totalDistanceTraveled += totals.distanceTraveled ?? 0;
    globalTotals.totalEquippedTimes += totals.equippedTimes ?? 0;
  }

  fullDescription =
    `§f§lGlobal Stats (All Players Combined)§r\n\n` +
    `§eTotal Kills: §f${globalTotals.totalKills}\n` +
    `§eTotal Damage Dealt: §f${Math.round(globalTotals.totalDamageDealt)}\n` +
    `§eTotal Damage Taken: §f${Math.round(globalTotals.totalDamageTaken)}\n` +
    `§eTotal Blocks Broken: §f${globalTotals.totalBlocksBroken}\n` +
    `§eTotal Blocks Placed: §f${globalTotals.totalBlocksPlaced}\n` +
    `§eTotal Distance Traveled: §f${Math.round(globalTotals.totalDistanceTraveled)} blocks\n` +
    `§eTotal Equipped Time: §f${formatTicksToTime(globalTotals.totalEquippedTimes)}\n`;
}
    form.body(fullDescription);
    form.button("§8⬅ Back");
    form.button("§c⤴ Home");

    const response = await form.show(player);
    if (!response || response.canceled) return;

    if (response.selection === 0) {
      return this.showItemMenu(player, category, subcategory);
    }
    if (response.selection === 1) {
      return this.showCategoryMenu(player);
    }
  }

  show(player) {
    return this.showCategoryMenu(player);
  }
}

export { CustomForm, loadUnlockedHats, resetSessionStatsForAllPlayers };