import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../bloc/game_bloc.dart'; import '../services/level_service.dart'; import '../game/models/level.dart'; import 'game_screen.dart'; class LevelSelectionScreen extends StatefulWidget { const LevelSelectionScreen({super.key}); @override State createState() => _LevelSelectionScreenState(); } class _LevelSelectionScreenState extends State { List? _levelsWithProgress; bool _isLoading = true; String? _error; @override void initState() { super.initState(); _loadLevels(); } Future _loadLevels() async { try { final levelsWithProgress = await LevelService.instance.getLevelsWithProgress(); setState(() { _levelsWithProgress = levelsWithProgress; _isLoading = false; }); } catch (e) { setState(() { _error = e.toString(); _isLoading = false; }); } } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.purple, Colors.deepPurple], ), ), child: SafeArea( child: Column( children: [ // Header Padding( padding: const EdgeInsets.all(20.0), child: Row( children: [ IconButton( onPressed: () => Navigator.pop(context), icon: const Icon(Icons.arrow_back, color: Colors.white, size: 30), ), const Expanded( child: Text( 'Select Level', textAlign: TextAlign.center, style: TextStyle( fontSize: 32, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), const SizedBox(width: 50), // Balance the back button ], ), ), // Content Expanded( child: _buildContent(), ), ], ), ), ), ); } Widget _buildContent() { if (_isLoading) { return const Center( child: CircularProgressIndicator(color: Colors.white), ); } if (_error != null) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error, color: Colors.white, size: 64), const SizedBox(height: 16), const Text( 'Error loading levels', style: const TextStyle(color: Colors.white, fontSize: 18), ), const SizedBox(height: 8), Text( _error!, style: const TextStyle(color: Colors.white70, fontSize: 14), textAlign: TextAlign.center, ), const SizedBox(height: 16), ElevatedButton( onPressed: () { setState(() { _isLoading = true; _error = null; }); _loadLevels(); }, child: const Text('Retry'), ), ], ), ); } if (_levelsWithProgress == null || _levelsWithProgress!.isEmpty) { return const Center( child: Text( 'No levels available', style: TextStyle(color: Colors.white, fontSize: 18), ), ); } return Padding( padding: const EdgeInsets.all(20.0), child: GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 16, mainAxisSpacing: 16, childAspectRatio: 0.8, ), itemCount: _levelsWithProgress!.length, itemBuilder: (context, index) { final levelWithProgress = _levelsWithProgress![index]; return _buildLevelCard(levelWithProgress); }, ), ); } Widget _buildLevelCard(LevelWithProgress levelWithProgress) { final level = levelWithProgress.level; final progress = levelWithProgress.progress; final isUnlocked = levelWithProgress.isUnlocked; final isCompleted = levelWithProgress.isCompleted; return GestureDetector( onTap: isUnlocked ? () => _startLevel(level) : null, child: Container( decoration: BoxDecoration( color: isUnlocked ? Colors.white : Colors.grey.shade400, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Level number Container( width: 50, height: 50, decoration: BoxDecoration( color: isUnlocked ? (isCompleted ? Colors.green : Colors.blue) : Colors.grey, shape: BoxShape.circle, ), child: Center( child: isUnlocked ? Text( '${level.id}', style: const TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), ) : const Icon( Icons.lock, color: Colors.white, size: 24, ), ), ), const SizedBox(height: 8), // Level name Text( level.name, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: isUnlocked ? Colors.black87 : Colors.grey.shade600, ), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 4), // Stars (if completed) if (isCompleted) ...[ Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(3, (starIndex) { return Icon( starIndex < progress.stars ? Icons.star : Icons.star_border, color: starIndex < progress.stars ? Colors.amber : Colors.grey, size: 16, ); }), ), const SizedBox(height: 4), Text( 'Best: ${progress.bestScore}', style: TextStyle( fontSize: 10, color: Colors.grey.shade600, ), ), ] else if (isUnlocked) ...[ // Level constraints info _buildConstraintInfo(level), ], ], ), ), ); } Widget _buildConstraintInfo(Level level) { final constraints = []; if (level.constraints.hasScoreTarget) { constraints.add('${level.constraints.targetScore!} pts'); } if (level.constraints.hasMoveLimit) { constraints.add('${level.constraints.maxMoves!} moves'); } if (level.constraints.hasTimeLimit) { constraints.add('${level.constraints.timeLimit!}s'); } if (level.objectives.hasGemTypeObjectives) { constraints.add('Clear gems'); } return Column( children: constraints .take(2) .map( (constraint) => Text( constraint, style: TextStyle( fontSize: 10, color: Colors.grey.shade600, ), ), ) .toList(), ); } void _startLevel(Level level) { // Start the level first print("Starting Level ${level.id}"); // Then navigate to game screen Navigator.push( context, MaterialPageRoute( builder: (context) => BlocProvider.value( value: context.read(), child: GameScreen( levelId: level.id, gridHeight: level.gridHeight, gridWidth: level.gridWidth, ), ), ), ).then((_) { // Refresh levels when returning from game _loadLevels(); }); } }