import 'country_code_sources/cached_country_code_source.dart'; import 'country_code_sources/country_code_source.dart'; import 'country_code_sources/gps_country_code_source.dart'; import 'country_code_sources/manual_country_code_source.dart'; import 'country_code_sources/sim_country_code_source.dart'; /// Orchestriert die priorisierte Ermittlungskette für den aktuellen /// Ländercode (`docs/plan.md`, Abschnitt 6 + 8, AP4 + AP6): /// /// 0. manuelle Auswahl des Nutzers (`shared_preferences`, übersteuert alles) /// 1. SIM/Netz-Ländercode (offline, primär) /// 2. GPS + Reverse-Geocoding (Fallback, ggf. Netz nötig) /// 3. zuletzt gespeicherter Code (`shared_preferences`) /// /// Die erste Quelle, die einen nicht-`null`-Wert liefert, gewinnt; die /// übrigen Quellen werden dann nicht mehr angefragt. Nach einem Treffer über /// SIM oder GPS wird der Cache best-effort aktualisiert (Fehler dabei /// beeinflussen die Rückgabe nicht), damit ein späterer Aufruf ohne /// Netz/GPS/SIM trotzdem einen aktuellen Wert liefern kann. Die manuelle /// Auswahl (Stufe 0) wird bewusst **nicht** in diesen automatischen Cache /// (Stufe 3) geschrieben – beides sind getrennte Mechanismen mit eigenem /// `shared_preferences`-Key, siehe `ManualCountryCodeSource` und /// `CachedCountryCodeSource`. /// /// `null` wird nur zurückgegeben, wenn wirklich alle Quellen fehlschlagen – /// die UI (AP5+) muss diesen Fall (`status = countryUnknown`) explizit /// behandeln. class LocationService { LocationService({ CountryCodeSource? simSource, CountryCodeSource? gpsSource, CountryCodeCache? cacheSource, ManualCountryCodeStore? manualSource, }) : _simSource = simSource ?? const SimCountryCodeSource(), _gpsSource = gpsSource ?? GpsCountryCodeSource(), _cacheSource = cacheSource ?? const CachedCountryCodeSource(), _manualSource = manualSource ?? const ManualCountryCodeSource(); final CountryCodeSource _simSource; final CountryCodeSource _gpsSource; final CountryCodeCache _cacheSource; final ManualCountryCodeStore _manualSource; Future resolveCountryCode() async { final manualResult = await _manualSource.resolve(); if (manualResult != null) { return manualResult; } final simResult = await _simSource.resolve(); if (simResult != null) { await _cacheSource.save(simResult); return simResult; } final gpsResult = await _gpsSource.resolve(); if (gpsResult != null) { await _cacheSource.save(gpsResult); return gpsResult; } return _cacheSource.resolve(); } /// Setzt oder löscht die manuelle Länderauswahl (`docs/plan.md`, /// Abschnitt 8, AP6). `isoCode == null` löscht eine zuvor gesetzte Auswahl /// wieder, sodass der nächste [resolveCountryCode]-Aufruf wieder auf die /// automatische Kette (SIM → GPS → Cache) zurückfällt. Future setManualCountryCode(String? isoCode) => _manualSource.save(isoCode); }