import 'dart:async'; import 'package:quiz_app/core/endpoint/api_endpoint.dart'; import 'package:quiz_app/core/utils/logger.dart'; import 'package:socket_io_client/socket_io_client.dart' as io; class SocketService { late io.Socket socket; final _roomMessageController = StreamController>.broadcast(); final _chatMessageController = StreamController>.broadcast(); final _questionUpdateController = StreamController>.broadcast(); final _quizStartedController = StreamController.broadcast(); final _answerSubmittedController = StreamController>.broadcast(); final _scoreUpdateController = StreamController>.broadcast(); final _quizDoneController = StreamController.broadcast(); final _roomClosedController = StreamController.broadcast(); final _errorController = StreamController.broadcast(); // Public streams Stream> get roomMessages => _roomMessageController.stream; Stream> get questionUpdate => _questionUpdateController.stream; Stream> get chatMessages => _chatMessageController.stream; Stream get quizStarted => _quizStartedController.stream; Stream> get answerSubmitted => _answerSubmittedController.stream; Stream> get scoreUpdates => _scoreUpdateController.stream; Stream get quizDone => _quizDoneController.stream; Stream get roomClosed => _roomClosedController.stream; Stream get errors => _errorController.stream; void initSocketConnection() { socket = io.io( APIEndpoint.baseUrl, io.OptionBuilder().setTransports(['websocket']).disableAutoConnect().build(), ); socket.connect(); socket.onConnect((_) { logC.i('✅ Connected: ${socket.id}'); }); socket.onDisconnect((_) { logC.i('❌ Disconnected'); }); socket.on('connection_response', (data) { logC.i('🟢 Connection response: $data'); }); socket.on('room_message', (data) { logC.i('📥 Room Message: $data'); _roomMessageController.add(Map.from(data)); }); socket.on('receive_message', (data) { logC.i('💬 Chat from ${data['from']}: ${data['message']}'); _chatMessageController.add(Map.from(data)); }); socket.on('quiz_started', (_) { logC.i('🚀 Quiz Started!'); _quizStartedController.add(null); }); socket.on('quiz_question', (data) { logC.i('🚀 question getted!'); _questionUpdateController.add(Map.from(data)); }); socket.on('answer_submitted', (data) { logC.i('✅ Answer Submitted: $data'); _answerSubmittedController.add(Map.from(data)); }); socket.on('score_update', (data) { logC.i('📊 Score Update: $data'); _scoreUpdateController.add(Map.from(data)); }); socket.on('quiz_done', (_) { logC.i('🏁 Quiz Finished!'); _quizDoneController.add(null); }); socket.on('room_closed', (data) { logC.i('🔒 Room Closed: $data'); _roomClosedController.add(data['room'].toString()); }); socket.on('error', (data) { logC.e('⚠️ Socket Error: $data'); _errorController.add(data.toString()); }); } void joinRoom({required String sessionCode, required String userId}) { socket.emit('join_room', { 'session_code': sessionCode, 'user_id': userId, }); } void leaveRoom({required String sessionId, required String userId, String username = "anonymous"}) { socket.emit('leave_room', { 'session_id': sessionId, 'user_id': userId, 'username': username, }); } void sendMessage({ required String sessionId, required String message, String username = "anonymous", }) { socket.emit('send_message', { 'session_id': sessionId, 'message': message, 'username': username, }); } void startQuiz({required String sessionId}) { socket.emit('start_quiz', { 'session_id': sessionId, }); } void sendAnswer({ required String sessionId, required String userId, required int questionIndex, required int timeSpent, required dynamic answer, }) { socket.emit('submit_answer', { 'session_id': sessionId, 'user_id': userId, 'question_index': questionIndex, 'answer': answer, 'time_spent': timeSpent, }); } void endSession({required String sessionId, required String userId}) { socket.emit('end_session', { 'session_id': sessionId, 'user_id': userId, }); } void dispose() { socket.dispose(); _roomMessageController.close(); _chatMessageController.close(); _quizStartedController.close(); _answerSubmittedController.close(); _scoreUpdateController.close(); _quizDoneController.close(); _roomClosedController.close(); _errorController.close(); } }