# -*- coding: utf-8 -*-
"""
umlaute.py - Sicheres Ersetzen von Ersatzschreibungen (ae/oe/ue/ss) durch echte
Umlaute (ä/ö/ü/ß) in deutschen Texten.

Strategie: NICHT pauschal ersetzen (das wuerde Woerter wie "Aerodynamik" oder
englische Begriffe zerstoeren), sondern:
  1) Eine Ausnahmeliste schuetzt Woerter mit echtem ae/oe/ue/ss.
  2) Regelbasiert werden nur typische deutsche Muster ersetzt.
  3) Token fuer Token, Gross-/Kleinschreibung bleibt erhalten.

Anwendung: clean_text(s) auf jeden sichtbaren String. HTML-Tags (<b>, <i>) und
Platzhalter bleiben unberuehrt, weil sie keine ae/oe/ue-Muster enthalten.
"""
import re

# Woerter, die echtes ae/oe/ue/ss tragen und NICHT angefasst werden duerfen.
# (klein geschrieben; Vergleich case-insensitive)
SCHUTZ = {
    "aero", "aerodynamik", "aerobic", "aerosol", "israel", "michael", "raphael",
    "duell", "duett", "etui", "aktuell", "individuell", "manuell", "sexuell",
    "visuell", "spirituell", "intellektuell", "rituell", "aktuelle", "aktuellen",
    "duo", "statue", "statuen", "influencer", "queue", "februar",
    "muesli", "suite", "tuell",
    # ss-Schutz: Fremdwoerter / Faelle, wo ss korrekt ist
    "boss", "fitness", "wellness", "business", "stress", "express", "adresse",
    "kompromiss", "fluss", "schloss", "kuss", "biss", "riss", "guss", "nass",
    "pass", "klasse", "tasse", "masse", "gasse", "wasser", "besser", "wissen",
    "essen", "lassen", "messen", "passen", "wachsen", "russland", "russisch",
    "interesse", "prozess", "kongress", "diskussion", "session", "passion",
    "missy", "miss", "essenz", "essenziell", "obsession",
}

# Direkte Wort-Ersetzungen (haeufigste Faelle, eindeutig).
# Kleinschreibung; Gross-Varianten werden automatisch abgeleitet.
WORTLISTE = {
    "fuer": "für", "fuers": "fürs", "wofuer": "wofür", "dafuer": "dafür",
    "ueber": "über", "ueberhaupt": "überhaupt", "uebersetzen": "übersetzen",
    "uebersetzt": "übersetzt", "uebrig": "übrig", "uebung": "übung",
    "ueblich": "üblich", "ueberall": "überall", "uebernehmen": "übernehmen",
    "ueberlasten": "überlasten", "ueberlastung": "überlastung",
    "gegenueber": "gegenüber", "gefuehl": "gefühl", "gefuehle": "gefühle",
    "gefuehlen": "gefühlen", "gefuehls": "gefühls", "bauchgefuehl": "bauchgefühl",
    "geborgenheitsgefuehl": "geborgenheitsgefühl",
    "fuehl": "fühl", "fuehlt": "fühlt", "fuehlst": "fühlst", "fuehlen": "fühlen",
    "fuehle": "fühle", "fuehlend": "fühlend", "fuehlenden": "fühlenden",
    "anfuehlt": "anfühlt", "anfuehlen": "anfühlen",
    "fuehr": "führ", "fuehrt": "führt", "fuehren": "führen", "fuehrung": "führung",
    "anfuehrung": "anführung", "anfuehrungszeichen": "anführungszeichen",
    "muessen": "müssen", "muesste": "müsste", "muesstest": "müsstest",
    "wuerde": "würde", "wuerden": "würden", "wuerdest": "würdest",
    "wuerdevoll": "würdevoll", "wuerdig": "würdig",
    "moechte": "möchte", "moechtest": "möchtest", "moechten": "möchten",
    "moeglich": "möglich", "moeglichkeit": "möglichkeit",
    "moeglichkeiten": "möglichkeiten", "moeglichst": "möglichst",
    "unmoeglich": "unmöglich",
    "koerper": "körper", "koerperlich": "körperlich", "koerperliche": "körperliche",
    "koerperlichen": "körperlichen", "koerperliches": "körperliches",
    "verkoerpern": "verkörpern", "verkoerpert": "verkörpert",
    "schoen": "schön", "schoene": "schöne", "schoenen": "schönen",
    "schoenheit": "schönheit", "schoener": "schöner",
    "hoechste": "höchste", "hoechsten": "höchsten", "hoeher": "höher",
    "hoehe": "höhe", "hoehen": "höhen", "hoeren": "hören", "gehoert": "gehört",
    "stoeren": "stören", "stoert": "stört", "zerstoeren": "zerstören",
    "loesen": "lösen", "loest": "löst", "loesung": "lösung", "aufloesen": "auflösen",
    "groesse": "größe", "groesser": "größer", "groesste": "größte",
    "groessten": "größten", "groesseren": "größeren",
    "staerke": "stärke", "staerken": "stärken", "staerker": "stärker",
    "verstaerkt": "verstärkt", "verstaerken": "verstärken", "staerkste": "stärkste",
    "schwaeche": "schwäche", "schwaechen": "schwächen", "schwaecher": "schwächer",
    "waechst": "wächst", "waechs": "wächs",
    "aendern": "ändern", "aenderung": "änderung", "veraendern": "verändern",
    "veraenderung": "veränderung", "veraendert": "verändert",
    "naechste": "nächste", "naechsten": "nächsten", "naechster": "nächster",
    "spaeter": "später", "spaetestens": "spätestens",
    "haeuser": "häuser", "haeusern": "häusern",
    "erklaeren": "erklären", "erklaert": "erklärt", "erklaerung": "erklärung",
    "erklaerungen": "erklärungen",
    "waehlen": "wählen", "waehlt": "wählt", "gewaehlt": "gewählt",
    "auswaehlen": "auswählen", "waehle": "wähle",
    "raeume": "räume", "raeumen": "räumen", "raum": "raum",
    "traeume": "träume", "traeumen": "träumen", "traeumt": "träumt",
    "baeume": "bäume", "laeuft": "läuft", "laesst": "lässt",
    "autoritaet": "autorität", "autoritaeten": "autoritäten",
    "persoenlich": "persönlich", "persoenliche": "persönliche",
    "persoenlichen": "persönlichen", "persoenlichkeit": "persönlichkeit",
    "selbstfuersorge": "selbstfürsorge",
    "qualitaet": "qualität", "qualitaeten": "qualitäten",
    "realitaet": "realität", "identitaet": "identität",
    "aktivitaet": "aktivität", "intensitaet": "intensität",
    "sensibilitaet": "sensibilität", "stabilitaet": "stabilität",
    "klarheit": "klarheit",
    "taeglich": "täglich", "taetig": "tätig", "taetigkeit": "tätigkeit",
    "vertraeg": "verträg", "vertraegt": "verträgt", "ertraeg": "erträg",
    "zusammenhaeng": "zusammenhäng", "zusammenhaenge": "zusammenhänge",
    "zusammenhaengen": "zusammenhängen",
    "naehe": "nähe", "naehren": "nähren", "naehrt": "nährt", "ernaehrung": "ernährung",
    "erfaehrst": "erfährst", "erfaehrt": "erfährt",
    "gefaehr": "gefähr", "gefaehrlich": "gefährlich",
    "ungefaehr": "ungefähr", "faehig": "fähig", "faehigkeit": "fähigkeit",
    "faehigkeiten": "fähigkeiten",
    "regelmaessig": "regelmäßig", "gemaess": "gemäß", "massnahme": "maßnahme",
    "massnahmen": "maßnahmen", "massstab": "maßstab", "massgeblich": "maßgeblich",
    "draussen": "draußen", "aussen": "außen", "aeussere": "äußere",
    "aeusseren": "äußeren", "aeussert": "äußert", "aeusserst": "äußerst",
    "schliessen": "schließen", "schliesst": "schließt", "schliesslich": "schließlich",
    "ausschliesslich": "ausschließlich", "beschliessen": "beschließen",
    "geniessen": "genießen", "geniesst": "genießt", "geniesse": "genieße",
    "weiss": "weiß", "heisst": "heißt", "heissen": "heißen",
    "grosse": "große", "grossen": "großen", "gross": "groß", "grosser": "großer",
    "grosses": "großes", "grossartig": "großartig",
    "fuss": "fuß", "fuesse": "füße", "suess": "süß", "suesse": "süße",
    "bewusst": "bewusst", "selbstbewusst": "selbstbewusst",
    "schluessel": "schlüssel", "schluesselbegriff": "schlüsselbegriff",
    "gluecklich": "glücklich", "glueck": "glück", "ausdruecken": "ausdrücken",
    "drueck": "drück", "drueckt": "drückt", "ruecken": "rücken",
    "zurueck": "zurück", "stueck": "stück", "bruecke": "brücke",
    "fuenf": "fünf", "fuenfte": "fünfte", "huelle": "hülle",
    "ueberschrift": "überschrift", "ueberschriften": "überschriften",
    "augenhoehe": "augenhöhe",
    "erhaeltst": "erhältst", "erhaelt": "erhält", "erhaeltlich": "erhältlich",
    "kanaele": "kanäle", "kanaelen": "kanälen",
    "ratschlaege": "ratschläge", "ratschlaegen": "ratschlägen",
    "schluesselbegriffe": "schlüsselbegriffe",
    "steuerzeichen": "steuerzeichen",
    "ausser": "außer", "ausserdem": "außerdem", "aeusserung": "äußerung",
    "gueltiges": "gültiges", "gueltig": "gültig", "ungueltig": "ungültig",
    "staerksten": "stärksten", "staerkste": "stärkste",
    "tatsaechlich": "tatsächlich", "tatsaechliche": "tatsächliche",
    "tatsaechlichen": "tatsächlichen", "tatsaechlicher": "tatsächlicher",
    "anfuehrungszeichen2": "anführungszeichen",
    "absaetze": "absätze", "absaetzen": "absätzen",
    "woerter": "wörter", "woertern": "wörtern",
}


def _match_case(orig, repl):
    """Uebertraegt die Gross-/Kleinschreibung von orig auf repl."""
    if orig.isupper():
        return repl.upper()
    if orig[:1].isupper():
        return repl[:1].upper() + repl[1:]
    return repl


def _replace_token(tok):
    low = tok.lower()
    if low in SCHUTZ:
        return tok
    repl = WORTLISTE.get(low)
    if repl:
        return _match_case(tok, repl)
    return tok


_WORD_RE = re.compile(r"[A-Za-zÄÖÜäöüß]+")


def clean_text(s):
    """Ersetzt Ersatzschreibungen durch echte Umlaute - nur in bekannten Woertern.
    HTML-Tags und Platzhalter (%s, {x}) bleiben unangetastet, da sie keine
    Wort-Tokens der Liste treffen."""
    if not isinstance(s, str) or not s:
        return s
    return _WORD_RE.sub(lambda m: _replace_token(m.group(0)), s)


def clean_obj(obj):
    """Wendet clean_text rekursiv auf Strings in dict/list/tuple an."""
    if isinstance(obj, str):
        return clean_text(obj)
    if isinstance(obj, dict):
        return {k: clean_obj(v) for k, v in obj.items()}
    if isinstance(obj, list):
        return [clean_obj(v) for v in obj]
    if isinstance(obj, tuple):
        return tuple(clean_obj(v) for v in obj)
    return obj
