"""Reifenzähler ohne utility_meter (§7.5, §10 Punkt 6).

ABWEICHUNG VOM URSPRÜNGLICHEN LASTENHEFT (Frontend-Anpassung, nach dem
ursprünglichen Bau nachträglich verlangt): früher war der Zähler = aktueller
Kilometerstand - fester Startwert je Satz (reifen.saetze.<satz>.
start_odo_km). Das war falsch, sobald einmal zwischen Sommer und Winter
umgeschaltet wurde: die Differenz zum Startwert zählt dann alle seither
gefahrenen Kilometer mit, auch die auf dem jeweils anderen Satz. Jetzt gilt
stattdessen: jeder gefahrene Kilometer wird dem Satz zugerechnet, der zum
Zeitpunkt der Fahrt aktiv war. Dafür führt reifen.saetze.<satz>.km selbst den
fortlaufenden Gesamtstand (statt eines Startwerts), und reifen.
referenz_odo_km hält den zuletzt verarbeiteten Kilometerstand fest, gegen den
die nächste Änderung als Delta gemessen wird. start_odo_km/§13 entfällt
damit vollständig.

Ergebnis wird zusätzlich als eigene pyscript-Zustandsvariable bereitgestellt
(nur zur Kontrolle in Entwicklerwerkzeuge → Zustände, das Frontend liest die
Werte direkt aus dem veröffentlichten Profil):
  pyscript.reifen_sommer_km, pyscript.reifen_winter_km,
  pyscript.reifen_aktiver_satz

Kein Abhängigkeit von total_increasing oder utility_meter-internem Zustand -
die Fortschreibung braucht nur den zuletzt bekannten Absolutwert des
Kilometerstand-Sensors. Ein zeitweise `unavailable` Quellsensor (§4.1)
verliert dadurch nichts: referenz_odo_km bleibt einfach stehen, bis wieder
ein gültiger Wert kommt, und das nächste Delta wird dann gegen diesen alten
Stand berechnet - auch km, die während eines HA-Neustarts/Ausfalls gefahren
wurden, werden so noch dem damals aktiven Satz zugerechnet.

Entity-IDs stehen zentral in pyscript/modules/einstellungen.py.
"""

import einstellungen
import frontend_veroeffentlichung
import profil


def _aktueller_km():
    try:
        return float(frontend_veroeffentlichung.zustand_oder_none(einstellungen.KM_SENSOR))
    except (TypeError, ValueError):
        return None


def _zustaende_veroeffentlichen(p):
    reifen = p.get("reifen", {})
    saetze = reifen.get("saetze", {})
    for satz_name in ("sommer", "winter"):
        km = saetze.get(satz_name, {}).get("km")
        if km is None:
            state.set(f"pyscript.reifen_{satz_name}_km", "unbekannt")
        else:
            state.set(f"pyscript.reifen_{satz_name}_km", km, new_attributes={"unit_of_measurement": "km"})
    state.set("pyscript.reifen_aktiver_satz", reifen.get("aktiv", "unbekannt"))


def _fortschreiben_und_veroeffentlichen(neuer_km, neuer_aktiv=None):
    """Rechnet zuerst mit dem bisher aktiven Satz ab (Delta seit
    referenz_odo_km), trägt danach optional einen Satzwechsel ein - in dieser
    Reihenfolge, damit beim Wechseln selbst keine km dem neuen Satz
    zugerechnet werden, die eigentlich noch auf dem alten gefahren wurden."""
    p = profil.profil_lesen()
    if p is None:
        return
    reifen = p.setdefault("reifen", {})
    saetze = reifen.setdefault("saetze", {})
    aktiv = reifen.get("aktiv", "sommer")
    referenz = reifen.get("referenz_odo_km")

    if referenz is not None and neuer_km is not None:
        delta = round(neuer_km - referenz, 1)
        if delta > 0:
            satz = saetze.setdefault(aktiv, {})
            satz["km"] = round((satz.get("km") or 0) + delta, 1)
    if neuer_km is not None:
        reifen["referenz_odo_km"] = neuer_km
    if neuer_aktiv is not None:
        reifen["aktiv"] = neuer_aktiv

    profil.profil_schreiben(p)
    frontend_veroeffentlichung.profil_veroeffentlichen()
    _zustaende_veroeffentlichen(p)


@time_trigger("startup")
def beim_start():
    _fortschreiben_und_veroeffentlichen(_aktueller_km())


@state_trigger(f"{einstellungen.KM_SENSOR}")
def kilometerstand_geaendert(value=None):
    _fortschreiben_und_veroeffentlichen(_aktueller_km())


@service
def audi_dashboard_reifen_wechseln(satz=None):
    """Umschalten des aktiven Reifensatzes (§5.2). Aufruf als
    pyscript.audi_dashboard_reifen_wechseln mit satz="sommer"|"winter"."""
    if satz not in ("sommer", "winter"):
        log.warning(f"audi_dashboard: ungültiger Reifensatz '{satz}'")
        return
    _fortschreiben_und_veroeffentlichen(_aktueller_km(), neuer_aktiv=satz)
    log.info(f"audi_dashboard: aktiver Reifensatz auf '{satz}' umgeschaltet")
