import { FIGHTER, SPAWN } from "../constants.js"; const STORAGE_KEYS = { names: "arena.match.playerNames", spawnPlacement: "arena.match.spawnPlacement", }; export function createMatchForm() { const form = getElement("#fighter-form"); const namesInput = getElement("#player-names"); const namesWarningNode = getElement("#player-names-warning"); const namesWarningTitleNode = getElement("[data-player-names-warning-title]"); const namesWarningCountNode = getElement("[data-player-names-warning-count]"); const namesWarningLimitNode = getElement("[data-player-names-warning-limit]"); const namesWarningReasonNode = getElement("[data-player-names-warning-reason]"); const appNode = document.querySelector("#app"); const statusNode = document.querySelector("#match-status"); const statusTextNodes = document.querySelectorAll("[data-status-text]"); const spawnPlacementInputs = getElements('input[name="spawnPlacement"]'); const setPlayerNamesWarning = (warning = null) => { const hasWarning = Boolean(warning); if (!hasWarning) { namesWarningNode.hidden = true; namesInput.removeAttribute("aria-invalid"); return; } namesWarningTitleNode.textContent = warning.title; namesWarningCountNode.textContent = warning.fighterCount.toLocaleString("ko-KR"); namesWarningLimitNode.textContent = warning.maxFighterCount.toLocaleString("ko-KR"); namesWarningReasonNode.textContent = warning.reason ?? ""; namesWarningReasonNode.hidden = !warning.reason; namesWarningNode.hidden = false; namesInput.setAttribute("aria-invalid", "true"); }; const readMatchConfig = () => ({ names: nicknameValues(namesInput.value), spawnPlacement: selectedSpawnPlacement(spawnPlacementInputs), }); restoreSavedMatchSettings(namesInput, spawnPlacementInputs); namesInput.addEventListener("input", () => { setPlayerNamesWarning(); saveMatchSettings(namesInput, spawnPlacementInputs); }); spawnPlacementInputs.forEach((input) => { input.addEventListener("change", () => { saveMatchSettings(namesInput, spawnPlacementInputs); }); }); return { onSubmit(handler) { form.addEventListener("submit", (event) => { event.preventDefault(); handler(readMatchConfig()); }); }, readMatchConfig, setPlayerNamesWarning, setStatus(message) { if (statusNode) { statusNode.setAttribute("aria-hidden", "false"); statusNode.title = message; } statusTextNodes.forEach((node) => { node.textContent = message; }); appNode?.classList.add("status-active"); }, }; } function getElement(selector) { const element = document.querySelector(selector); if (!element) { throw new Error(`Missing required element: ${selector}`); } return element; } function getElements(selector) { const elements = [...document.querySelectorAll(selector)]; if (elements.length === 0) { throw new Error(`Missing required elements: ${selector}`); } return elements; } function nicknameValues(value) { return value .split(/\r?\n|,/) .map((name) => name.trim().slice(0, FIGHTER.NICKNAME_LENGTH)) .filter(Boolean); } function restoreSavedMatchSettings(namesInput, spawnPlacementInputs) { const storage = getLocalStorage(); if (!storage) { return; } try { const savedNames = storage.getItem(STORAGE_KEYS.names); const savedSpawnPlacement = storage.getItem(STORAGE_KEYS.spawnPlacement); if (savedNames !== null) { namesInput.value = savedNames; } setSpawnPlacement(spawnPlacementInputs, savedSpawnPlacement); } catch { // Storage may be unavailable in private or restricted browser contexts. } } function saveMatchSettings(namesInput, spawnPlacementInputs) { const storage = getLocalStorage(); if (!storage) { return; } try { storage.setItem(STORAGE_KEYS.names, namesInput.value); storage.setItem(STORAGE_KEYS.spawnPlacement, selectedSpawnPlacement(spawnPlacementInputs)); } catch { // Ignore storage failures so the match form remains usable. } } function selectedSpawnPlacement(inputs) { return inputs.find((input) => input.checked)?.value ?? SPAWN.DEFAULT_PLACEMENT; } function setSpawnPlacement(inputs, value) { const savedInput = inputs.find((input) => input.value === value); const defaultInput = inputs.find((input) => input.value === SPAWN.DEFAULT_PLACEMENT); const nextInput = savedInput ?? defaultInput; if (nextInput) { nextInput.checked = true; } } function getLocalStorage() { try { return window.localStorage; } catch { return null; } }