flowchart TD
    A["HyprTile Launcher"] -->|"F5"| B["xmpp_overlay"]

    B --> State["XmppOverlayState"]
    State --> Visible["visible"]
    State --> BackendStarted["backend_started"]
    State --> Connected["connected"]
    State --> SelectedContact["selected_contact"]
    State --> Scrolls["contact_scroll / chat_scroll"]
    State --> ChildProc["pid + stdin/stdout/stderr FDs"]
    State --> Account["account_alias"]
    State --> SelfJid["self_jid"]
    State --> Input["input bis 32768 Bytes"]
    State --> Status["status / last_stderr"]
    State --> Buffers["stdout_buf / stderr_buf"]

    A --> MainLoop["hyprtile.c Event Loop"]
    MainLoop --> F5["SDLK_F5"]
    F5 --> Toggle["xmpp_overlay_toggle_visible"]
    Toggle --> CloseOthers["andere Overlays schließen"]
    CloseOthers --> B

    MainLoop --> TextInput["SDL_EVENT_TEXT_INPUT"]
    TextInput -->|"wenn XMPP sichtbar"| AppendText["xmpp_overlay_append_text"]

    MainLoop --> KeyInput["SDL_EVENT_KEY_DOWN"]
    KeyInput -->|"Ctrl+A/C/V"| SelectCopyPaste["Select all / Copy / Paste"]
    KeyInput -->|"Esc"| Close["Overlay schließen"]
    KeyInput -->|"Backspace/Delete"| EditInput["Input bearbeiten"]
    KeyInput -->|"Left/Right/Home/End"| CursorMove["Cursor bewegen"]
    KeyInput -->|"Enter"| SendInput["xmpp_overlay_send_input"]
    KeyInput -->|"Up/Down/Tab"| ContactOrInputScroll["Kontakt wechseln oder Composer scrollen"]

    MainLoop --> Mouse["Mouse Events"]
    Mouse --> MouseButton["handle_xmpp_overlay_mouse_button"]
    Mouse --> MouseMotion["handle_xmpp_overlay_mouse_motion"]
    Mouse --> MouseUp["handle_xmpp_overlay_mouse_button_up"]
    Mouse --> MouseWheel["handle_xmpp_overlay_mouse_wheel"]

    MainLoop --> RenderLoop["Render Loop"]
    RenderLoop --> Update["xmpp_overlay_update_if_needed"]
    RenderLoop --> Render["render_xmpp_overlay"]

    B --> UI["XMPP Overlay UI"]
    UI --> Panel["1280x800 Panel"]
    UI --> ContactsPane["Kontaktliste links"]
    UI --> ChatPane["Chatverlauf rechts"]
    UI --> Composer["Composer unten"]
    UI --> SendButton["Send Button"]
    UI --> Footer["F5/Esc · Enter senden · Mausrad · Bildklick"]

    ContactsPane --> Contacts["XmppContact[] bis 256"]
    Contacts --> ContactFields["jid / name / preview / last_seen"]

    ChatPane --> Items["ChatItem[] bis 1024"]
    Items --> MessageItem["CHAT_ITEM_MESSAGE"]
    Items --> AttachmentItem["CHAT_ITEM_ATTACHMENT"]
    Items --> SystemItem["CHAT_ITEM_SYSTEM"]

    MessageItem --> MessageFields["from / to / body / timestamp / outgoing"]
    AttachmentItem --> AttachmentFields["url / name / content_type / kind / local_path / is_image"]
    SystemItem --> SystemText["Status-/Fehlermeldungen"]

    B --> History["Lokaler Verlauf"]
    History --> BaseDir["~/.hyprtile/messages"]
    BaseDir --> DomainDir["Domain-Verzeichnis"]
    DomainDir --> PeerDir["Peer-Verzeichnis"]
    PeerDir --> Jsonl["messages.jsonl"]
    History --> LastSelected[".last_selected"]

    Items --> Persist["xmpp_history_persist_item"]
    Persist --> Jsonl
    Jsonl --> LoadHistory["xmpp_history_load_all"]
    LoadHistory --> Contacts
    LoadHistory --> Items
    LastSelected --> RestoreSelection["xmpp_history_restore_selected_contact"]

    B --> Backend["hyprtile-xmppclient Backend"]
    Backend --> ResolveBinary["xmpp_resolve_binary"]
    ResolveBinary --> BinPath["hyprtile-xmppclient/hyprtile-xmppclient"]

    Toggle --> StartBackend["xmpp_start_backend"]
    StartBackend --> Pipes["stdin / stdout / stderr Pipes"]
    Pipes --> Fork["fork"]
    Fork --> Child["Child Process"]
    Child --> Chdir["chdir Backend-Verzeichnis"]
    Chdir --> Exec["exec ./hyprtile-xmppclient --account <alias> --json"]
    Exec --> DebugMode{"HYPRTILE_XMPP_DEBUG != 0?"}
    DebugMode -->|"Ja"| ExecDebug["--debug zusätzlich"]
    DebugMode -->|"Nein"| ExecNormal["nur --json"]

    Backend --> RosterOnce["xmpp_load_roster_once"]
    RosterOnce --> RosterCmd["--account <alias> --roster"]
    RosterCmd --> RosterJson["Roster JSON"]
    RosterJson --> ParseRoster["xmpp_parse_roster_json"]
    ParseRoster --> Contacts

    SendInput --> HasContact{"Kontakt ausgewählt?"}
    HasContact -->|"Nein"| NoContact["Status: Kein Kontakt ausgewählt"]
    HasContact -->|"Ja"| DetectCommand{"Input beginnt mit /file ?"}

    DetectCommand -->|"Nein"| SendMsg["JSON: send_message"]
    SendMsg --> MsgPayload["to + body"]
    DetectCommand -->|"Ja"| SendFile["JSON: send_file"]
    SendFile --> FilePayload["to + path"]

    MsgPayload --> WriteJson["xmpp_write_json_line"]
    FilePayload --> WriteJson
    WriteJson --> BackendStdin["Backend stdin"]

    Backend --> BackendStdout["Backend stdout"]
    BackendStdout --> StdoutBuffer["stdout_buf sammeln"]
    StdoutBuffer --> ConsumeLines["xmpp_consume_stream_buffer"]
    ConsumeLines --> EventLine["xmpp_handle_event_line"]

    EventLine --> EventType{"event"}
    EventType -->|"connected"| ConnectedEvent["connected=1 / self_jid / Status"]
    EventType -->|"message"| IncomingMessage["Message ChatItem"]
    EventType -->|"attachment"| IncomingAttachment["Attachment ChatItem"]
    EventType -->|"error"| ErrorEvent["Status + System Item"]
    EventType -->|"stopped"| StoppedEvent["connected=0"]
    EventType -->|"file_pending"| FilePending["Upload vorbereitet"]
    EventType -->|"upload_done"| UploadDone["Upload fertig"]
    EventType -->|"upload_service"| UploadService["Upload-Service gefunden"]

    IncomingMessage --> BareJid["bare JID bestimmen"]
    IncomingAttachment --> BareJid
    BareJid --> UpdateContact["Kontakt anlegen/aktualisieren"]
    UpdateContact --> Preview["Preview aktualisieren"]
    IncomingMessage --> AddItem["xmpp_add_item"]
    IncomingAttachment --> AddItem
    ErrorEvent --> AddItem
    AddItem --> Persist

    AttachmentItem --> AttachmentCache["XmppAttachmentTexture Cache"]
    AttachmentCache --> Download["Attachment in Cache laden"]
    Download --> DecodeImage["Bild via FFmpeg dekodieren"]
    DecodeImage --> SDLTexture["SDL_Texture"]
    SDLTexture --> ChatPane

    MouseButton --> ClickRect["XmppClickRect"]
    ClickRect --> OpenAttachment["Attachment öffnen"]
    OpenAttachment --> XdgOpen["xdg-open"]
    ClickRect --> ImageViewer["integrierter Bildviewer"]

    ImageViewer --> Zoom["Zoom"]
    ImageViewer --> Pan["Pan / Drag"]
    ImageViewer --> CloseViewer["Schließen"]

    Render --> DrawContacts["Kontakte rendern"]
    Render --> DrawChat["Nachrichten / Attachments rendern"]
    Render --> DrawComposer["Composer mit dynamischer Höhe"]
    Render --> DrawStatus["Statuszeile"]
    Render --> DrawViewer["Bildviewer falls aktiv"]