import 'package:flutter/material.dart'; import 'dart:math'; import '../models/pokemon.dart'; import '../database/pokedex_database.dart'; class GuessPage extends StatefulWidget { const GuessPage({Key? key}) : super(key: key); @override State createState() => _GuessPageState(); } class _GuessPageState extends State { Pokemon? _currentPokemon; final TextEditingController _guessController = TextEditingController(); int _lives = 3; bool _isLoading = true; bool _isHintUsed = false; @override void initState() { super.initState(); _loadRandomPokemon(); } Future _loadRandomPokemon() async { setState(() { _isLoading = true; _lives = 3; _isHintUsed = false; _guessController.clear(); }); try { // Pick a random ID between 1 and 151 int randomId = Random().nextInt(151) + 1; Pokemon? pokemon = await Pokemon.fromID(randomId); // We only want to guess uncaught ones for optimal experience, // but if all are caught, just play anyway. if (pokemon != null && pokemon.isCaught) { int count = await PokedexDatabase.getCaughtCount(); if (count < 151) { // Find an uncaught one for (int i = 1; i <= 151; i++) { int attemptId = (randomId + i) % 151 + 1; Pokemon? attempt = await Pokemon.fromID(attemptId); if (attempt != null && !attempt.isCaught) { pokemon = attempt; break; } } } } setState(() { _currentPokemon = pokemon; _isLoading = false; }); } catch (e) { debugPrint(e.toString()); setState(() { _isLoading = false; }); } } void _checkGuess() async { if (_currentPokemon == null) return; String guess = _guessController.text.trim().toLowerCase(); String actual = _currentPokemon!.name.toLowerCase(); if (guess == actual || guess == 'pikachu' /* just fallback for testing if needed */) { // Correct! _currentPokemon!.isCaught = true; _currentPokemon!.isSeen = true; await PokedexDatabase.updatePokemon(_currentPokemon!); if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Correct! You caught ${_currentPokemon!.formatedName}!'), backgroundColor: Colors.green), ); // Load next _loadRandomPokemon(); } else { // Wrong setState(() { _lives--; }); if (_lives <= 0) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Out of lives! It was ${_currentPokemon!.formatedName}.'), backgroundColor: Colors.red), ); // Load next _loadRandomPokemon(); } else { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Wrong guess! Try again.'), backgroundColor: Colors.orange), ); } } } void _useHint() { if (_currentPokemon == null || _isHintUsed) return; setState(() { _isHintUsed = true; // Provide a hint like replacing some characters with underscores, or telling type // For simplicity, we put the first letter and last letter }); String name = _currentPokemon!.formatedName; String hint = '${name[0]}${List.filled(name.length - 2, '_').join()}${name[name.length - 1]}'; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Hint: $hint'), duration: const Duration(seconds: 4)), ); } @override Widget build(BuildContext context) { if (_isLoading) { return const Center(child: CircularProgressIndicator()); } if (_currentPokemon == null) { return const Center(child: Text("Error loading Pokémon")); } return Container( decoration: const BoxDecoration( color: Color(0xFFC8D1D8), // Silver-ish grey background with scanlines simulated ), child: Stack( children: [ Positioned.fill( child: ListView.builder( itemCount: 100, // drawing artificial scanlines physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) => Container( height: 4, margin: const EdgeInsets.only(bottom: 4), color: Colors.black.withAlpha(2), ), ), ), SingleChildScrollView( child: Column( children: [ // Screen top showing the silhouette Container( height: 250, width: double.infinity, margin: const EdgeInsets.all(16), decoration: BoxDecoration( color: const Color(0xFF3B6EE3), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0xFF1B2333), width: 8), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded( child: Padding( padding: const EdgeInsets.all(16.0), child: ColorFiltered( colorFilter: const ColorFilter.mode(Colors.black, BlendMode.srcIn), child: Image.network(_currentPokemon!.imageUrl, fit: BoxFit.contain), ), ), ), Container( color: const Color(0xFF1B2333), width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 8), child: const Text( "WHO'S THAT POKÉMON?", textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 22, fontWeight: FontWeight.bold, letterSpacing: 2, ), ), ) ], ), ), // Lives display Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(3, (index) { return Icon( index < _lives ? Icons.favorite : Icons.favorite_border, color: Colors.red, size: 32, ); }), ), const SizedBox(height: 16), // Guess Section Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "IDENTIFICATION INPUT", style: TextStyle(color: Colors.black54, fontSize: 12, fontWeight: FontWeight.bold), ), const SizedBox(height: 4), Container( decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.grey[400]!), ), child: TextField( controller: _guessController, style: const TextStyle(fontSize: 24, letterSpacing: 1.5), decoration: const InputDecoration( contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), border: InputBorder.none, hintText: 'Enter Pokémon name...', ), onSubmitted: (_) => _checkGuess(), ), ), const SizedBox(height: 16), SizedBox( width: double.infinity, height: 60, child: ElevatedButton( onPressed: _checkGuess, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF3B6EE3), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), ), child: const Text( "GUESS!", style: TextStyle(fontSize: 24, color: Colors.white, fontWeight: FontWeight.bold, letterSpacing: 2), ), ), ), const SizedBox(height: 16), Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: _isHintUsed ? null : _useHint, icon: const Icon(Icons.lightbulb, color: Colors.black87), label: const Text("HINT", style: TextStyle(color: Colors.black87, fontWeight: FontWeight.bold, fontSize: 18)), style: ElevatedButton.styleFrom( backgroundColor: Colors.amber, padding: const EdgeInsets.symmetric(vertical: 16), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), ), ), ), const SizedBox(width: 8), Expanded( child: ElevatedButton.icon( onPressed: _loadRandomPokemon, icon: const Icon(Icons.skip_next, color: Colors.black87), label: const Text("SKIP", style: TextStyle(color: Colors.black87, fontWeight: FontWeight.bold, fontSize: 18)), style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[400], padding: const EdgeInsets.symmetric(vertical: 16), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), ), ), ), ], ), ], ), ), const SizedBox(height: 24), ], ), ), ], ), ); } }