import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../data/data_sources/remote/geviserver_remote_data_source.dart'; import 'geviserver_event.dart'; import 'geviserver_state.dart'; class GeViServerBloc extends Bloc { final GeViServerRemoteDataSource remoteDataSource; GeViServerBloc({required this.remoteDataSource}) : super(const GeViServerState()) { on(_onConnect); on(_onDisconnect); on(_onCheckStatus); on(_onSendCrossSwitch); on(_onClearVideoOutput); on(_onCloseContact); on(_onOpenContact); on(_onSendCustomAction); on(_onSendMessage); on(_onStartTimer); on(_onStopTimer); on(_onClearActionResult); } Future _onConnect( ConnectGeViServerEvent event, Emitter emit, ) async { emit(state.copyWith( connectionStatus: ConnectionStatus.connecting, isLoading: true, clearErrorMessage: true, )); try { final result = await remoteDataSource.connect( address: event.address, username: event.username, password: event.password, ); if (result['success'] == true) { emit(state.copyWith( connectionStatus: ConnectionStatus.connected, serverAddress: event.address, username: event.username, connectedAt: DateTime.now(), isLoading: false, lastActionResult: 'Connected to ${event.address}', lastActionSuccess: true, )); } else { emit(state.copyWith( connectionStatus: ConnectionStatus.error, isLoading: false, errorMessage: result['message'] ?? 'Connection failed', lastActionResult: result['message'] ?? 'Connection failed', lastActionSuccess: false, )); } } catch (e) { emit(state.copyWith( connectionStatus: ConnectionStatus.error, isLoading: false, errorMessage: e.toString(), lastActionResult: 'Connection error: $e', lastActionSuccess: false, )); } } Future _onDisconnect( DisconnectGeViServerEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { await remoteDataSource.disconnect(); emit(state.copyWith( connectionStatus: ConnectionStatus.disconnected, isLoading: false, clearServerAddress: true, clearUsername: true, clearConnectedAt: true, lastActionResult: 'Disconnected', lastActionSuccess: true, )); } catch (e) { emit(state.copyWith( isLoading: false, errorMessage: e.toString(), lastActionResult: 'Disconnect error: $e', lastActionSuccess: false, )); } } Future _onCheckStatus( CheckStatusEvent event, Emitter emit, ) async { try { final result = await remoteDataSource.getStatus(); final isConnected = result['is_connected'] == true; emit(state.copyWith( connectionStatus: isConnected ? ConnectionStatus.connected : ConnectionStatus.disconnected, serverAddress: result['address']?.toString(), username: result['username']?.toString(), )); } catch (e) { emit(state.copyWith( connectionStatus: ConnectionStatus.error, errorMessage: e.toString(), )); } } Future _onSendCrossSwitch( SendCrossSwitchEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { final result = await remoteDataSource.crossSwitch( videoInput: event.videoInput, videoOutput: event.videoOutput, switchMode: event.switchMode, ); final message = 'CrossSwitch(${event.videoInput}, ${event.videoOutput}, ${event.switchMode})'; _addToLog(emit, message); emit(state.copyWith( isLoading: false, lastActionResult: result['success'] == true ? 'CrossSwitch sent successfully' : result['message'] ?? 'CrossSwitch failed', lastActionSuccess: result['success'] == true, )); } catch (e) { emit(state.copyWith( isLoading: false, lastActionResult: 'CrossSwitch error: $e', lastActionSuccess: false, )); } } Future _onClearVideoOutput( ClearVideoOutputEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { final result = await remoteDataSource.clearOutput( videoOutput: event.videoOutput, ); final message = 'ClearVideoOutput(${event.videoOutput})'; _addToLog(emit, message); emit(state.copyWith( isLoading: false, lastActionResult: result['success'] == true ? 'ClearOutput sent successfully' : result['message'] ?? 'ClearOutput failed', lastActionSuccess: result['success'] == true, )); } catch (e) { emit(state.copyWith( isLoading: false, lastActionResult: 'ClearOutput error: $e', lastActionSuccess: false, )); } } Future _onCloseContact( CloseContactEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { final result = await remoteDataSource.closeContact( contactId: event.contactId, ); final message = 'CloseContact(${event.contactId})'; _addToLog(emit, message); emit(state.copyWith( isLoading: false, lastActionResult: result['success'] == true ? 'CloseContact sent successfully' : result['message'] ?? 'CloseContact failed', lastActionSuccess: result['success'] == true, )); } catch (e) { emit(state.copyWith( isLoading: false, lastActionResult: 'CloseContact error: $e', lastActionSuccess: false, )); } } Future _onOpenContact( OpenContactEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { final result = await remoteDataSource.openContact( contactId: event.contactId, ); final message = 'OpenContact(${event.contactId})'; _addToLog(emit, message); emit(state.copyWith( isLoading: false, lastActionResult: result['success'] == true ? 'OpenContact sent successfully' : result['message'] ?? 'OpenContact failed', lastActionSuccess: result['success'] == true, )); } catch (e) { emit(state.copyWith( isLoading: false, lastActionResult: 'OpenContact error: $e', lastActionSuccess: false, )); } } Future _onSendCustomAction( SendCustomActionEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { final result = await remoteDataSource.sendCustomAction( typeId: event.typeId, text: event.text, ); final message = 'CustomAction(${event.typeId}, "${event.text}")'; _addToLog(emit, message); emit(state.copyWith( isLoading: false, lastActionResult: result['success'] == true ? 'CustomAction sent successfully' : result['message'] ?? 'CustomAction failed', lastActionSuccess: result['success'] == true, )); } catch (e) { emit(state.copyWith( isLoading: false, lastActionResult: 'CustomAction error: $e', lastActionSuccess: false, )); } } Future _onSendMessage( SendMessageEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { final result = await remoteDataSource.sendMessage(event.message); _addToLog(emit, event.message); emit(state.copyWith( isLoading: false, lastActionResult: result['success'] == true ? 'Message sent successfully' : result['message'] ?? 'Send message failed', lastActionSuccess: result['success'] == true, )); } catch (e) { emit(state.copyWith( isLoading: false, lastActionResult: 'Send message error: $e', lastActionSuccess: false, )); } } Future _onStartTimer( StartTimerEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { final result = await remoteDataSource.startTimer( timerId: event.timerId, timerName: event.timerName, ); final message = 'StartTimer(${event.timerId}, "${event.timerName}")'; _addToLog(emit, message); emit(state.copyWith( isLoading: false, lastActionResult: result['success'] == true ? 'StartTimer sent successfully' : result['message'] ?? 'StartTimer failed', lastActionSuccess: result['success'] == true, )); } catch (e) { emit(state.copyWith( isLoading: false, lastActionResult: 'StartTimer error: $e', lastActionSuccess: false, )); } } Future _onStopTimer( StopTimerEvent event, Emitter emit, ) async { emit(state.copyWith(isLoading: true)); try { final result = await remoteDataSource.stopTimer( timerId: event.timerId, timerName: event.timerName, ); final message = 'StopTimer(${event.timerId}, "${event.timerName}")'; _addToLog(emit, message); emit(state.copyWith( isLoading: false, lastActionResult: result['success'] == true ? 'StopTimer sent successfully' : result['message'] ?? 'StopTimer failed', lastActionSuccess: result['success'] == true, )); } catch (e) { emit(state.copyWith( isLoading: false, lastActionResult: 'StopTimer error: $e', lastActionSuccess: false, )); } } void _onClearActionResult( ClearActionResultEvent event, Emitter emit, ) { emit(state.copyWith(clearLastActionResult: true, clearErrorMessage: true)); } void _addToLog(Emitter emit, String message) { final timestamp = DateTime.now().toIso8601String().substring(11, 19); final logEntry = '[$timestamp] $message'; final newLog = [...state.messageLog, logEntry]; // Keep only last 100 messages if (newLog.length > 100) { newLog.removeRange(0, newLog.length - 100); } emit(state.copyWith(messageLog: newLog)); } }