import { getSavedLevels } from "./levelEditor"; import { LevelConfig } from "./levelConfig"; import { ProgressionManager } from "./progression"; import { GameConfig } from "./gameConfig"; import { AuthService } from "./authService"; import debugLog from './debug'; const SELECTED_LEVEL_KEY = 'space-game-selected-level'; // Default level order for the carousel const DEFAULT_LEVEL_ORDER = [ 'Rookie Training', 'Rescue Mission', 'Deep Space Patrol', 'Enemy Territory', 'The Gauntlet', 'Final Challenge' ]; /** * Populate the level selection screen with saved levels * Shows all 6 default levels in a 3x2 carousel with locked/unlocked states */ export async function populateLevelSelector(): Promise { const container = document.getElementById('levelCardsContainer'); if (!container) { console.warn('Level cards container not found'); return false; } const savedLevels = getSavedLevels(); const gameConfig = GameConfig.getInstance(); const progressionEnabled = gameConfig.progressionEnabled; const progression = ProgressionManager.getInstance(); if (savedLevels.size === 0) { container.innerHTML = `

No Levels Found

Something went wrong - default levels should be auto-generated!

Go to Level Editor
`; return false; } // Separate default and custom levels const defaultLevels = new Map(); const customLevels = new Map(); for (const [name, config] of savedLevels.entries()) { if (config.metadata?.type === 'default') { defaultLevels.set(name, config); } else { customLevels.set(name, config); } } let html = ''; // Show progression stats only if progression is enabled if (progressionEnabled) { const completedCount = progression.getCompletedCount(); const totalCount = progression.getTotalDefaultLevels(); const completionPercent = progression.getCompletionPercentage(); const nextLevel = progression.getNextLevel(); html += `

Progress

${completedCount} of ${totalCount} default levels completed (${completionPercent.toFixed(0)}%)
${nextLevel ? `
Next: ${nextLevel}
` : ''}
`; } // Check if user is authenticated (ASYNC!) const authService = AuthService.getInstance(); const isAuthenticated = await authService.isAuthenticated(); const isTutorial = (levelName: string) => levelName === DEFAULT_LEVEL_ORDER[0]; debugLog('[LevelSelector] Authenticated:', isAuthenticated); debugLog('[LevelSelector] Progression enabled:', progressionEnabled); debugLog('[LevelSelector] Tutorial level name:', DEFAULT_LEVEL_ORDER[0]); debugLog('[LevelSelector] Default levels count:', defaultLevels.size); debugLog('[LevelSelector] Default level names:', Array.from(defaultLevels.keys())); // Show all 6 default levels in order (3x2 grid) if (defaultLevels.size > 0) { for (const levelName of DEFAULT_LEVEL_ORDER) { const config = defaultLevels.get(levelName); if (!config) { // Level doesn't exist - show empty slot html += `

${levelName}

🔒
Level not found

This level has not been created yet.

`; continue; } const description = config.metadata?.description || `${config.asteroids.length} asteroids • ${config.planets.length} planets`; const estimatedTime = config.metadata?.estimatedTime || ''; const isCompleted = progressionEnabled && progression.isLevelComplete(levelName); // Check if level is unlocked: // - Tutorial is always unlocked // - If authenticated: check progression unlock status // - If not authenticated: only Tutorial is unlocked let isUnlocked = false; const isTut = isTutorial(levelName); if (isTut) { isUnlocked = true; // Tutorial always unlocked debugLog(`[LevelSelector] ${levelName}: Tutorial - always unlocked`); } else if (!isAuthenticated) { isUnlocked = false; // Non-tutorial levels require authentication debugLog(`[LevelSelector] ${levelName}: Not authenticated - locked`); } else { isUnlocked = !progressionEnabled || progression.isLevelUnlocked(levelName); debugLog(`[LevelSelector] ${levelName}: Authenticated - unlocked:`, isUnlocked); } const isCurrentNext = progressionEnabled && progression.getNextLevel() === levelName; // Determine card state let cardClasses = 'level-card'; let statusIcon = ''; let buttonText = 'Play Level'; let buttonDisabled = ''; let lockReason = ''; if (isCompleted) { cardClasses += ' level-card-completed'; statusIcon = '
✓
'; buttonText = 'Replay'; } else if (isCurrentNext && isUnlocked) { cardClasses += ' level-card-current'; statusIcon = '
START HERE
'; } else if (!isUnlocked) { cardClasses += ' level-card-locked'; statusIcon = '
🔒
'; // Determine why it's locked if (!isAuthenticated && !isTutorial(levelName)) { buttonText = 'Sign In Required'; lockReason = '
Sign in to unlock
'; } else if (progressionEnabled) { const levelIndex = DEFAULT_LEVEL_ORDER.indexOf(levelName); if (levelIndex > 0) { const previousLevel = DEFAULT_LEVEL_ORDER[levelIndex - 1]; lockReason = `
Complete "${previousLevel}" to unlock
`; } buttonText = 'Locked'; } else { buttonText = 'Locked'; } buttonDisabled = ' disabled'; } html += `

${levelName}

${statusIcon}
Difficulty: ${config.difficulty}${estimatedTime ? ` • ${estimatedTime}` : ''}

${description}

${lockReason}
`; } } // Show custom levels section if any exist if (customLevels.size > 0) { html += `

Custom Levels

`; for (const [name, config] of customLevels.entries()) { const description = config.metadata?.description || `${config.asteroids.length} asteroids • ${config.planets.length} planets`; const author = config.metadata?.author ? ` by ${config.metadata.author}` : ''; html += `

${name}

Custom${author} • ${config.difficulty}

${description}

`; } } container.innerHTML = html; // Attach event listeners to all level buttons const buttons = container.querySelectorAll('.level-button:not([disabled])'); buttons.forEach(button => { button.addEventListener('click', (e) => { const target = e.target as HTMLButtonElement; const levelName = target.getAttribute('data-level'); if (levelName) { selectLevel(levelName); } }); }); return true; } /** * Select a level and dispatch event to start it */ export function selectLevel(levelName: string): void { debugLog(`[LevelSelector] Level selected: ${levelName}`); const savedLevels = getSavedLevels(); const config = savedLevels.get(levelName); if (!config) { console.error(`Level not found: ${levelName}`); return; } // Save selected level localStorage.setItem(SELECTED_LEVEL_KEY, levelName); // Dispatch custom event that Main class will listen for const event = new CustomEvent('levelSelected', { detail: { levelName, config } }); window.dispatchEvent(event); } /** * Get the last selected level name */ export function getSelectedLevel(): string | null { return localStorage.getItem(SELECTED_LEVEL_KEY); }