import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:geolocator/geolocator.dart'; import '../../services/geolocation.dart'; import '../models/ptv_logistic_model.dart'; import '../services/ptv_api_simple.dart'; /// GetX Controller für Geolocation Funktionalität class GeolocationController extends GetxController { // Reactive Variablen final _currentPosition = Rxn(); final _statusText = 'Noch keine Position ermittelt'.obs; final _isTracking = false.obs; final _isLoading = false.obs; final _ptvModel = Rxn(); // Getter für reactive Variablen Position? get currentPosition => _currentPosition.value; String get statusText => _statusText.value; bool get isTracking => _isTracking.value; bool get isLoading => _isLoading.value; PTVModel? get ptvModel => _ptvModel.value; @override void onClose() { // Cleanup beim Schließen des Controllers stopTracking(); super.onClose(); } /// Holt die aktuelle Position einmalig Future getCurrentPosition() async { try { _isLoading.value = true; _statusText.value = 'Position wird ermittelt...'; Position? position = await GeolocationService.getCurrentPosition(); if (position != null) { _currentPosition.value = position; _statusText.value = GeolocationService.positionToString(position); var resultData = await PtvApiServiceSimple.getLocationsByPosition( latitude: position.latitude, longitude: position.longitude, ); if (resultData != null) { _ptvModel.value = PTVModel.fromJson(resultData); } else { _ptvModel.value = null; } debugPrint('Position ermittelt: ${_currentPosition.value}'); } else { _statusText.value = 'Position konnte nicht ermittelt werden'; debugPrint('Fehler beim Abrufen der Position'); // Fehler-Snackbar anzeigen Get.snackbar( 'Fehler', 'Position konnte nicht ermittelt werden', snackPosition: SnackPosition.BOTTOM, ); } } catch (e) { _statusText.value = 'Fehler beim Abrufen der Position: $e'; Get.snackbar( 'Fehler', 'Unerwarteter Fehler: $e', snackPosition: SnackPosition.BOTTOM, ); } finally { _isLoading.value = false; } } /// Startet kontinuierliches Position Tracking Future startTracking() async { if (_isTracking.value) return; try { _isLoading.value = true; _statusText.value = 'Tracking wird gestartet...'; bool success = await GeolocationService.startPositionStream( onPositionChanged: (Position position) { _currentPosition.value = position; _statusText.value = GeolocationService.positionToString(position); }, onError: (String error) { _statusText.value = 'Tracking Fehler: $error'; _isTracking.value = false; Get.snackbar( 'Tracking Fehler', error, snackPosition: SnackPosition.BOTTOM, ); }, accuracy: LocationAccuracy.high, distanceFilter: 5, // Updates alle 5 Meter ); if (success) { _isTracking.value = true; _statusText.value = 'Tracking aktiv - Warten auf erste Position...'; Get.snackbar( 'Tracking gestartet', 'Position wird kontinuierlich überwacht', snackPosition: SnackPosition.BOTTOM, ); } else { _statusText.value = 'Tracking konnte nicht gestartet werden'; Get.snackbar( 'Fehler', 'Tracking konnte nicht gestartet werden', snackPosition: SnackPosition.BOTTOM, ); } } catch (e) { _statusText.value = 'Fehler beim Starten des Trackings: $e'; Get.snackbar( 'Fehler', 'Tracking-Fehler: $e', snackPosition: SnackPosition.BOTTOM, ); } finally { _isLoading.value = false; } } /// Stoppt das Position Tracking Future stopTracking() async { if (!_isTracking.value) return; try { await GeolocationService.stopPositionStream(); _isTracking.value = false; _statusText.value = 'Tracking gestoppt'; Get.snackbar( 'Tracking gestoppt', 'Position wird nicht mehr überwacht', snackPosition: SnackPosition.BOTTOM, ); } catch (e) { Get.snackbar( 'Fehler', 'Fehler beim Stoppen des Trackings: $e', snackPosition: SnackPosition.BOTTOM, ); } } /// Togglet das Tracking (Start/Stop) Future toggleTracking() async { if (_isTracking.value) { await stopTracking(); } else { await startTracking(); } } /// Prüft Permission Status Future checkPermissions() async { try { _isLoading.value = true; _statusText.value = 'Berechtigungen werden geprüft...'; LocationPermission permission = await GeolocationService.checkPermission(); bool serviceEnabled = await GeolocationService.isLocationServiceEnabled(); _statusText.value = 'Service aktiv: $serviceEnabled\n' 'Berechtigung: ${LocationPermissionHelper.getPermissionStatusText(permission)}'; // Detaillierte Information in Snackbar String permissionStatus = LocationPermissionHelper.getPermissionStatusText(permission); Get.snackbar( 'Berechtigungs-Status', 'Location Service: ${serviceEnabled ? "Aktiv" : "Inaktiv"}\n$permissionStatus', snackPosition: SnackPosition.BOTTOM, duration: const Duration(seconds: 4), ); } catch (e) { _statusText.value = 'Fehler beim Prüfen der Berechtigungen: $e'; Get.snackbar( 'Fehler', 'Berechtigungen konnten nicht geprüft werden: $e', snackPosition: SnackPosition.BOTTOM, ); } finally { _isLoading.value = false; } } /// Öffnet die Location Einstellungen Future openLocationSettings() async { try { bool opened = await GeolocationService.openLocationSettings(); if (opened) { Get.snackbar( 'Einstellungen geöffnet', 'Location-Einstellungen wurden geöffnet', snackPosition: SnackPosition.BOTTOM, ); } else { Get.snackbar( 'Fehler', 'Location-Einstellungen konnten nicht geöffnet werden', snackPosition: SnackPosition.BOTTOM, ); } } catch (e) { Get.snackbar( 'Fehler', 'Fehler beim Öffnen der Location-Einstellungen: $e', snackPosition: SnackPosition.BOTTOM, ); } } /// Öffnet die App Einstellungen Future openAppSettings() async { try { bool opened = await GeolocationService.openAppSettings(); if (opened) { Get.snackbar( 'Einstellungen geöffnet', 'App-Einstellungen wurden geöffnet', snackPosition: SnackPosition.BOTTOM, ); } else { Get.snackbar( 'Fehler', 'App-Einstellungen konnten nicht geöffnet werden', snackPosition: SnackPosition.BOTTOM, ); } } catch (e) { Get.snackbar( 'Fehler', 'Fehler beim Öffnen der App-Einstellungen: $e', snackPosition: SnackPosition.BOTTOM, ); } } /// Formatiert die aktuelle Position als lesbaren String String get formattedPosition { if (_currentPosition.value == null) return 'Keine Position verfügbar'; return GeolocationService.positionToString(_currentPosition.value!); } /// Prüft ob eine Position verfügbar ist bool get hasPosition => _currentPosition.value != null; /// Holt die Genauigkeit der aktuellen Position double get currentAccuracy => _currentPosition.value?.accuracy ?? 0.0; /// Holt die Geschwindigkeit der aktuellen Position in km/h double get currentSpeedKmh { if (_currentPosition.value?.speed == null) return 0.0; return (_currentPosition.value!.speed * 3.6); // m/s zu km/h } /// Resettet alle Werte auf ihre Anfangszustände void reset() { stopTracking(); _currentPosition.value = null; _statusText.value = 'Noch keine Position ermittelt'; _isTracking.value = false; _isLoading.value = false; } }