import 'package:flutter/material.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:provider/provider.dart'; import '../estado/estado_juego.dart'; import '../modelos/palabra.dart'; import '../modelos/partida.dart'; import '../tema/tema_app.dart'; import 'pantalla_ver_palabra.dart'; class PantallaCrearPartida extends StatefulWidget { const PantallaCrearPartida({super.key}); @override State createState() => _PantallaCrearPartidaState(); } class _PantallaCrearPartidaState extends State { bool _modoMultimovil = false; String _categoria = 'todas'; int _numImpostores = 1; bool _pistaImpostor = false; int? _tiempoDebate; final List _jugadores = []; final _controladorNombre = TextEditingController(); final _opcionesTiempo = [null, 60, 120, 180, 300]; int get _maxImpostores => (_jugadores.length / 3).floor().clamp(1, 4); List _etiquetasTiempo(AppLocalizations l10n) => [l10n.noLimit, l10n.oneMin, l10n.twoMin, l10n.threeMin, l10n.fiveMin]; void _agregarJugador() { final l10n = AppLocalizations.of(context)!; final nombre = _controladorNombre.text.trim(); if (nombre.isEmpty) return; if (_jugadores.contains(nombre)) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(l10n.playerAlreadyExists)), ); return; } if (_jugadores.length >= 20) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(l10n.maxPlayersReached)), ); return; } setState(() { _jugadores.add(nombre); _controladorNombre.clear(); if (_numImpostores > _maxImpostores) { _numImpostores = _maxImpostores; } }); } void _eliminarJugador(int index) { setState(() { _jugadores.removeAt(index); if (_numImpostores > _maxImpostores && _maxImpostores > 0) { _numImpostores = _maxImpostores; } }); } void _iniciarPartida() { final l10n = AppLocalizations.of(context)!; if (_jugadores.length < 3) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(l10n.minPlayersRequired)), ); return; } final estado = context.read(); estado.crearPartida( config: ConfigPartida( modoMultimovil: _modoMultimovil, categoria: _categoria, numImpostores: _numImpostores, pistaImpostor: _pistaImpostor, tiempoDebateSegundos: _tiempoDebate, ), nombresJugadores: _jugadores, ); Navigator.pushReplacement( context, MaterialPageRoute(builder: (_) => const PantallaVerPalabra()), ); } @override void dispose() { _controladorNombre.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final estado = context.watch(); final categorias = ['todas', ...?estado.banco?.nombresCategorias]; final etiquetas = _etiquetasTiempo(l10n); return Scaffold( appBar: AppBar(title: Text(l10n.createGame)), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Modo de juego Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(l10n.gameMode, style: Theme.of(context).textTheme.titleLarge), const SizedBox(height: 12), SegmentedButton( segments: [ ButtonSegment( value: false, label: Text(l10n.singleDevice), icon: const Icon(Icons.phone_android), ), ButtonSegment( value: true, label: Text(l10n.multiDevice), icon: const Icon(Icons.devices), ), ], selected: {_modoMultimovil}, onSelectionChanged: (valor) { setState(() => _modoMultimovil = valor.first); }, ), ], ), ), ), const SizedBox(height: 12), // Categoría Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(l10n.category, style: Theme.of(context).textTheme.titleLarge), const SizedBox(height: 12), SizedBox( width: double.infinity, child: DropdownButtonFormField( initialValue: _categoria, decoration: const InputDecoration( prefixIcon: Icon(Icons.category), ), items: categorias.map((c) { return DropdownMenuItem( value: c, child: Text(BancoPalabras.nombreBonitoCategoria(c, l10n)), ); }).toList(), onChanged: (v) => setState(() => _categoria = v!), ), ), ], ), ), ), const SizedBox(height: 12), // Jugadores Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(l10n.playersCount(_jugadores.length), style: Theme.of(context).textTheme.titleLarge), Text(l10n.playersRangeHint, style: Theme.of(context).textTheme.bodyMedium), ], ), const SizedBox(height: 12), Row( children: [ Expanded( child: TextField( controller: _controladorNombre, decoration: InputDecoration( hintText: l10n.playerNameHint, prefixIcon: const Icon(Icons.person_add), ), textCapitalization: TextCapitalization.words, onSubmitted: (_) => _agregarJugador(), ), ), const SizedBox(width: 8), IconButton.filled( onPressed: _agregarJugador, icon: const Icon(Icons.add), ), ], ), const SizedBox(height: 8), ..._jugadores.asMap().entries.map((e) { return ListTile( leading: CircleAvatar( backgroundColor: TemaApp.colorTarjeta, child: Text('${e.key + 1}', style: const TextStyle(color: TemaApp.colorTexto)), ), title: Text(e.value), trailing: IconButton( icon: const Icon(Icons.close, color: TemaApp.colorAcento), onPressed: () => _eliminarJugador(e.key), ), dense: true, ); }), ], ), ), ), const SizedBox(height: 12), // Configuración de partida Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(l10n.configuration, style: Theme.of(context).textTheme.titleLarge), const SizedBox(height: 12), // Número de impostores Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(l10n.impostors), Row( children: [ IconButton( onPressed: _numImpostores > 1 ? () => setState(() => _numImpostores--) : null, icon: const Icon(Icons.remove_circle_outline), ), Text('$_numImpostores', style: Theme.of(context) .textTheme .titleLarge), IconButton( onPressed: _numImpostores < _maxImpostores ? () => setState(() => _numImpostores++) : null, icon: const Icon(Icons.add_circle_outline), ), ], ), ], ), // Pista para impostor SwitchListTile( title: Text(l10n.impostorClue), subtitle: Text(l10n.impostorClueDescription), value: _pistaImpostor, onChanged: (v) => setState(() => _pistaImpostor = v), contentPadding: EdgeInsets.zero, ), // Temporizador Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(l10n.debateTime), DropdownButton( value: _tiempoDebate, items: List.generate( _opcionesTiempo.length, (i) => DropdownMenuItem( value: _opcionesTiempo[i], child: Text(etiquetas[i]), ), ), onChanged: (v) => setState(() => _tiempoDebate = v), ), ], ), ], ), ), ), const SizedBox(height: 24), // Botón iniciar SizedBox( width: double.infinity, height: 56, child: ElevatedButton.icon( onPressed: _jugadores.length >= 3 ? _iniciarPartida : null, icon: const Icon(Icons.play_arrow), label: Text(l10n.startGame), style: ElevatedButton.styleFrom( textStyle: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(height: 16), ], ), ), ); } }