import 'dart:async'; import 'package:flutter/material.dart'; import 'package:farolero/l10n/generated/app_localizations.dart'; import 'package:farolero/modelos/inicio_partida_multijugador.dart'; import 'package:farolero/modelos/jugador.dart'; import 'package:farolero/pantallas/pantalla_notas_online.dart'; import 'package:farolero/pantallas/pantalla_revision_palabra.dart'; import 'package:farolero/pantallas/pantalla_votacion_cliente.dart'; import 'package:farolero/servicios/servicio_nearby.dart'; import 'package:farolero/tema/tema_app.dart'; import 'package:provider/provider.dart'; /// Pantalla que ve el jugador durante la fase de debate (multidispositivo). /// El cliente recibe el cambio de fase via Nearby y se navega aquí. class PantallaDebateCliente extends StatefulWidget { final int? tiempoDebateSegundos; final String? primerTurnoNombre; final String? partidaId; final String? pistaCategoria; final List jugadores; final List jugadoresControlados; final VoidCallback onSolicitarVotacion; const PantallaDebateCliente({ super.key, this.tiempoDebateSegundos, this.primerTurnoNombre, this.partidaId, this.pistaCategoria, this.jugadores = const [], this.jugadoresControlados = const [], required this.onSolicitarVotacion, }); @override State createState() => _PantallaDebateClienteState(); } class _PantallaDebateClienteState extends State { Timer? _timer; int _segundosRestantes = 0; bool _votacionSolicitada = false; OnMensajeCallback? _listener; ServicioNearby? _nearby; @override void initState() { super.initState(); _listener = (endpointId, mensaje) { if (!mounted || mensaje.tipo != TipoMensaje.fase) return; final fase = mensaje.datos['fase'] as String?; if (fase == 'votacion') { Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (_) => PantallaVotacionCliente( jugadores: widget.jugadores, jugadoresControlados: widget.jugadoresControlados, partidaId: widget.partidaId, pistaCategoria: widget.pistaCategoria, onVotos: _enviarVotos, ), ), ); } }; WidgetsBinding.instance.addPostFrameCallback((_) { final listener = _listener; if (listener != null && mounted) { _nearby = context.read(); _nearby!.onMensaje(listener); } }); if (widget.tiempoDebateSegundos != null) { _segundosRestantes = widget.tiempoDebateSegundos!; _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (_segundosRestantes > 0) { setState(() => _segundosRestantes--); } else { timer.cancel(); } }); } } @override void dispose() { _timer?.cancel(); final listener = _listener; if (listener != null) { _nearby?.removeMensajeListener(listener); } super.dispose(); } void _enviarVotos(Map votos) { final nearby = context.read(); if (nearby.hostEndpointId == null) return; for (final entry in votos.entries) { nearby.enviarMensaje( nearby.hostEndpointId!, MensajeP2P( tipo: TipoMensaje.voto, datos: { 'votanteId': entry.key, 'votadoId': entry.value, 'votoporId': entry.value, }, ), ); } } String _formatearTiempo(int segundos) { final min = segundos ~/ 60; final seg = segundos % 60; return "${min.toString().padLeft(2, '0')}:${seg.toString().padLeft(2, '0')}"; } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Scaffold( backgroundColor: TemaApp.colorFondo, appBar: AppBar( title: Text(l10n.debate), automaticallyImplyLeading: false, backgroundColor: Colors.transparent, elevation: 0, actions: [ IconButton( tooltip: l10n.seeYourWord, icon: const Icon(Icons.visibility), onPressed: widget.jugadoresControlados.isEmpty ? null : () => mostrarRevisionPalabraOnline( context: context, jugadoresControlados: widget.jugadoresControlados, pistaCategoria: widget.pistaCategoria, ), ), IconButton( tooltip: l10n.notesTitle, icon: const Icon(Icons.edit_note), onPressed: _puedeAbrirNotas ? () => Navigator.push( context, MaterialPageRoute( builder: (_) => PantallaNotasOnline( partidaId: widget.partidaId!, jugadores: widget.jugadores, autoresControlados: widget.jugadoresControlados, ), ), ) : null, ), ], ), body: Padding( padding: const EdgeInsets.all(24), child: Column( children: [ const Spacer(), // Timer if (widget.tiempoDebateSegundos != null) ...[ Container( padding: const EdgeInsets.all(32), decoration: BoxDecoration( color: _segundosRestantes == 0 ? TemaApp.colorAcento.withValues(alpha: 0.3) : TemaApp.colorTarjeta, borderRadius: BorderRadius.circular(24), ), child: Column( children: [ Text( _segundosRestantes == 0 ? l10n.timeUp : l10n.timeRemaining, style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 8), Text( _formatearTiempo(_segundosRestantes), style: Theme.of(context).textTheme.displayMedium?.copyWith( fontWeight: FontWeight.bold, color: _segundosRestantes == 0 ? TemaApp.colorAcento : TemaApp.colorTexto, ), ), ], ), ), const SizedBox(height: 32), ] else ...[ Text( l10n.debatePhaseActive, style: Theme.of(context).textTheme.headlineMedium, textAlign: TextAlign.center, ), const SizedBox(height: 16), ], // Instrucciones if (widget.primerTurnoNombre != null) ...[ Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: TemaApp.colorNaranja.withValues(alpha: 0.18), borderRadius: BorderRadius.circular(16), border: Border.all( color: TemaApp.colorNaranja.withValues(alpha: 0.65), ), ), child: Row( children: [ const Icon( Icons.record_voice_over, color: TemaApp.colorNaranja, ), const SizedBox(width: 12), Expanded( child: Text( 'Empieza ${widget.primerTurnoNombre} diciendo su palabra.', style: Theme.of(context).textTheme.titleMedium, ), ), ], ), ), const SizedBox(height: 16), ], Text( l10n.debateInstructions, textAlign: TextAlign.center, style: TextStyle( color: TemaApp.colorTextoSecundario, fontSize: 16, ), ), const Spacer(), // Botón solicitar votación SizedBox( width: double.infinity, height: 56, child: ElevatedButton.icon( onPressed: _votacionSolicitada ? null : () { setState(() => _votacionSolicitada = true); widget.onSolicitarVotacion(); }, icon: Icon(_votacionSolicitada ? Icons.hourglass_empty : Icons.how_to_vote), label: Text( _votacionSolicitada ? l10n.votacionSolicitada : l10n.solicitarVotacion, ), style: ElevatedButton.styleFrom( backgroundColor: _votacionSolicitada ? TemaApp.colorTarjeta : TemaApp.colorAcento, foregroundColor: Colors.white, textStyle: const TextStyle(fontSize: 16), ), ), ), ], ), ), ); } bool get _puedeAbrirNotas { return widget.partidaId != null && widget.jugadores.isNotEmpty && widget.jugadoresControlados.isNotEmpty; } }