import 'dart:async'; import 'package:flutter/foundation.dart'; import '../../data/models/location_reading.dart'; import '../../data/repositories/settings_repository.dart'; import '../../data/services/telemetry_bridge.dart'; import '../../data/services/weather_service.dart'; /// Location-based temperature fallback used only when OBD has no ambient value. class WeatherController extends ChangeNotifier { WeatherController( this._platform, this._settings, { WeatherService? weatherService, }) : _weatherService = weatherService ?? WeatherService(); final TelemetryPlatform _platform; final SettingsRepository _settings; final WeatherService _weatherService; bool _enabled = false; bool _loading = false; bool _active = false; bool _disposed = false; double? _temperatureCelsius; String? _locationName; String? _error; Timer? _refreshTimer; bool get enabled => _enabled; bool get loading => _loading; double? get temperatureCelsius => _temperatureCelsius; String? get locationName => _locationName; String? get error => _error; bool get hasTemperature => _enabled && _temperatureCelsius != null && _locationName != null; void initialize() { _enabled = _settings.weatherLocationTemperature; } Future start() async { if (!_enabled || _active) return; _active = true; await refresh(); _refreshTimer?.cancel(); _refreshTimer = Timer.periodic( const Duration(minutes: 15), (_) => unawaited(refresh()), ); } void stop() { _active = false; _refreshTimer?.cancel(); _refreshTimer = null; } /// Enables the fallback and asks for location access at that moment. Future setEnabled(bool value) async { if (value == _enabled) return true; if (value) { final granted = await _platform.ensureLocationPermission(); if (!granted) { _error = 'Location permission is required for weather.'; _notify(); return false; } } _enabled = value; await _settings.setWeatherLocationTemperature(value); if (value) { _active = true; await refresh(); _refreshTimer?.cancel(); _refreshTimer = Timer.periodic( const Duration(minutes: 15), (_) => unawaited(refresh()), ); } else { stop(); _temperatureCelsius = null; _locationName = null; _error = null; } _notify(); return true; } Future refresh() async { if (!_enabled || _loading) return; _loading = true; _notify(); try { final LocationReading location; try { location = await _platform.getLocation(); } on TelemetryException catch (problem) { _error = problem.message; _temperatureCelsius = null; _locationName = null; return; } final temperature = await _weatherService.temperatureCelsius( latitude: location.latitude, longitude: location.longitude, ); if (temperature == null) { _error = 'Weather is unavailable.'; _temperatureCelsius = null; _locationName = null; return; } _temperatureCelsius = temperature; _locationName = location.displayPlace; _error = null; } finally { _loading = false; _notify(); } } void _notify() { if (!_disposed) notifyListeners(); } @override void dispose() { _disposed = true; _refreshTimer?.cancel(); super.dispose(); } }