import 'dart:async'; import 'dart:math'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:location/location.dart'; import 'package:sefer_driver/constant/table_names.dart'; import '../../constant/box_name.dart'; import '../../constant/links.dart'; import '../../main.dart'; import '../../print.dart'; import '../home/captin/home_captain_controller.dart'; import '../home/payment/captain_wallet_controller.dart'; import 'battery_status.dart'; import 'crud.dart'; import 'encrypt_decrypt.dart'; class LocationController extends GetxController { LocationData? _currentLocation; late Location location = Location(); bool isLoading = false; late double heading = 0; late double previousTime = 0; late double latitude; late double totalDistance = 0; late double longitude; late DateTime time; late double speed = 0; bool isActive = false; late LatLng myLocation = LatLng(0, 0); String totalPoints = '0'; LocationData? get currentLocation => _currentLocation; Timer? _locationTimer; LatLng? _lastSavedPosition; @override void onInit() async { super.onInit(); location = Location(); await location.changeSettings( accuracy: LocationAccuracy.high, interval: 5000, distanceFilter: 0); await location.enableBackgroundMode(enable: true); await getLocation(); await startLocationUpdates(); totalPoints = Get.put(CaptainWalletController()).totalPoints.toString(); isActive = Get.put(HomeCaptainController()).isActive; } String getLocationArea(double latitude, double longitude) { final locations = box.read(BoxName.locationName) ?? []; for (final location in locations) { final locationData = location as Map; final minLatitude = double.tryParse(locationData['min_latitude'].toString()) ?? 0.0; final maxLatitude = double.tryParse(locationData['max_latitude'].toString()) ?? 0.0; final minLongitude = double.tryParse(locationData['min_longitude'].toString()) ?? 0.0; final maxLongitude = double.tryParse(locationData['max_longitude'].toString()) ?? 0.0; if (latitude >= minLatitude && latitude <= maxLatitude && longitude >= minLongitude && longitude <= maxLongitude) { box.write(BoxName.serverChosen, (locationData['server_link'])); return locationData['name']; } } box.write(BoxName.serverChosen, AppLink.seferCairoServer); return 'Cairo'; } int _insertCounter = 0; double? _lastSpeed; DateTime? _lastSpeedTime; Future startLocationUpdates() async { if (box.read(BoxName.driverID) != null) { _locationTimer = Timer.periodic(const Duration(seconds: 5), (timer) async { try { await BatteryNotifier.checkBatteryAndNotify(); totalPoints = Get.find().totalPoints.toString(); isActive = Get.find().isActive; if (isActive && double.parse(totalPoints) > -300) { await getLocation(); if (myLocation.latitude == 0 && myLocation.longitude == 0) return; String area = getLocationArea(myLocation.latitude, myLocation.longitude); final payload = { 'driver_id': box.read(BoxName.driverID).toString(), 'latitude': myLocation.latitude.toString(), 'longitude': myLocation.longitude.toString(), 'heading': heading.toString(), 'speed': (speed * 3.6).toStringAsFixed(1), 'distance': totalDistance.toStringAsFixed(2), 'status': box.read(BoxName.statusDriverLocation) ?? 'off', }; // ✅ تحديث للسيرفر await CRUD().post( link: box.read(BoxName.serverChosen) + '/ride/location/update.php', payload: payload, ); // ✅ تخزين في SQLite فقط إذا الرحلة On + تحرك أكثر من 10 متر if ((box.read(BoxName.statusDriverLocation) ?? 'off') == 'on') { if (_lastSavedPosition == null || _calculateDistanceInMeters(_lastSavedPosition!, myLocation) >= 10) { double currentSpeed = speed; // m/s double? acceleration = _calculateAcceleration(currentSpeed); await sql.insertData({ 'driver_id': box.read(BoxName.driverID).toString(), 'latitude': myLocation.latitude, 'longitude': myLocation.longitude, 'acceleration': acceleration ?? 0.0, 'created_at': DateTime.now().toIso8601String(), 'updated_at': DateTime.now().toIso8601String(), }, TableName.behavior); _lastSavedPosition = myLocation; } } // ✅ إدخال للسيرفر كل دقيقة _insertCounter++; // Log.print('_insertCounter: ${_insertCounter}'); if (_insertCounter == 12) { _insertCounter = 0; await CRUD().post( link: box.read(BoxName.serverChosen) + '/ride/location/add.php', payload: payload, ); } // ✅ تحديث الكاميرا Get.find() .mapHomeCaptainController ?.animateCamera( CameraUpdate.newLatLng( LatLng( myLocation.latitude, myLocation.longitude, ), ), ); } } catch (e) { print('Location update error: $e'); } }); } } void stopLocationUpdates() { _locationTimer?.cancel(); } Future getLocation() async { bool serviceEnabled = await location.serviceEnabled(); if (!serviceEnabled) { serviceEnabled = await location.requestService(); if (!serviceEnabled) return; } PermissionStatus permissionGranted = await location.hasPermission(); if (permissionGranted == PermissionStatus.denied) { permissionGranted = await location.requestPermission(); if (permissionGranted != PermissionStatus.granted) return; } Future.delayed(Duration(milliseconds: 500), () async { try { LocationData _locationData = await location.getLocation(); if (_locationData.latitude != null && _locationData.longitude != null) { myLocation = LatLng(_locationData.latitude!, _locationData.longitude!); } else { myLocation = LatLng(0, 0); } speed = _locationData.speed ?? 0; heading = _locationData.heading ?? 0; update(); } catch (e) { print("Error getting location: $e"); } }); } double _calculateDistanceInMeters(LatLng start, LatLng end) { const p = 0.017453292519943295; final a = 0.5 - cos((end.latitude - start.latitude) * p) / 2 + cos(start.latitude * p) * cos(end.latitude * p) * (1 - cos((end.longitude - start.longitude) * p)) / 2; return 12742 * 1000 * asin(sqrt(a)); // meters } double? _calculateAcceleration(double currentSpeed) { final now = DateTime.now(); if (_lastSpeed != null && _lastSpeedTime != null) { final deltaTime = now.difference(_lastSpeedTime!).inMilliseconds / 1000.0; // seconds if (deltaTime > 0) { final acceleration = (currentSpeed - _lastSpeed!) / deltaTime; _lastSpeed = currentSpeed; _lastSpeedTime = now; return double.parse(acceleration.toStringAsFixed(2)); } } _lastSpeed = currentSpeed; _lastSpeedTime = now; return null; } }