import 'dart:async'; import 'package:geolocator/geolocator.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; import '../../core/constants/gps_constants.dart'; /// Lightweight stateless wrapper around Geolocator. /// /// Only handles platform I/O — no business logic. class GpsService { static double? _lastValidHeading; /// Create a position stream with dynamic accuracy setting. static Stream createPositionStream({ LocationAccuracy accuracy = LocationAccuracy.high, }) { return Geolocator.getPositionStream( locationSettings: AndroidSettings( accuracy: accuracy, distanceFilter: 0, intervalDuration: Duration(milliseconds: 250), ), ); } static Future requestPermissions() async { final permission = await Permission.locationWhenInUse.request(); return permission.isGranted; } static Future isLocationServiceEnabled() async { return await Geolocator.isLocationServiceEnabled(); } static Future getCurrentPosition({ LocationAccuracy accuracy = LocationAccuracy.bestForNavigation, Duration timeLimit = const Duration(seconds: 60), }) async { try { return await Geolocator.getCurrentPosition( locationSettings: LocationSettings( accuracy: accuracy, timeLimit: timeLimit, ), ); } catch (_) { return null; } } static double getCachedHeading(double heading) { if (heading >= GpsConfig.VALID_HEADING_MIN && heading <= GpsConfig.VALID_HEADING_MAX) { _lastValidHeading = heading; return heading; } return _lastValidHeading ?? 0.0; } static String getCompassDirection(double heading) { final cachedHeading = getCachedHeading(heading); const directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; final index = ((cachedHeading + 22.5) / 45).floor() % 8; return directions[index]; } static String formatHeading(double heading) { final cachedHeading = getCachedHeading(heading); return '${cachedHeading.round()} ${getCompassDirection(heading)}'; } static Future setWakeLock(bool enable) async { await WakelockPlus.toggle(enable: enable); } }