"""
Duenner Python-Wrapper um das MIT-lizenzierte `tfmx_player/render_tfmx`
(siehe tools/tfmx_player/LICENSE, Copyright Peter Fors) -- rendert ein
TFMX-Musikstueck (<NAME>.TFX + <NAME>.SAM aus PCKELL.DAT) einmalig zu einer
WAV-Datei und cached das Ergebnis, damit die Intro-Sequenz die Musik per
pygame.mixer abspielen kann.

Warum Subprocess statt reinem Python-Reimplement: TFMX ist ein komplexes
Amiga-Tracker-Format (siehe tfmx.h, ~95KB reine Player-Logik). Das
MIT-lizenzierte C-Referenztool duerfen wir direkt nutzen (im Gegensatz zum
lizenzlosen C#-Referenzprojekt fuer PCX/BOB/MAP, das wir bewusst nur als
Format-Wissen genommen und selbst neu geschrieben haben). Fuer Musik-
Wiedergabe ist der Sound selbst das Ziel, nicht der Decoder-Code -- ein
funktionierender, korrekt lizenzierter Renderer ist hier der pragmatische
Weg statt TFMX in Python neu zu erfinden.

Gerenderte WAVs sind urheberrechtlich das Original-Spielmaterial (Musik),
werden daher NICHT ins Git-Repo committed (wie raw/ und extracted_dat/) --
liegen nur lokal im Cache-Verzeichnis.

MEHRERE SONGS PRO MODUL (Fund 22.07.2026 abends, Stefans Hinweis "das Spiel
hat noch wesentlich mehr Lieder"): ein einzelnes TFX-Modul kann intern
MEHRERE Songs buendeln (tfmx.h's v_songs[]/v_songs_count, ausgewaehlt per
start_song-Index). Stichprobe per Debug-Tool ergab:
  TITEL.TFX    -> 3 Songs (song0/1 lang/loopend >15s, song2 ~8.0s)
  TITEL2.TFX   -> 2 Songs (song0 ~2.04s = Rauser-Bling, song1 ~2.40s = Factor5-
                  Brausen -- Laenge passt zu Stefans "nur ein bisschen laenger
                  als der Rauser-Sound")
  ONGAME2.TFX  -> 14 Songs (>15s-Tracks vermutlich Level-Musik, song3/11/12
                  sehr kurz (0.16-1.36s) vermutlich Jingles/Stinger, song2/13
                  ~10.3s). Noch nicht im Detail zugeordnet -- fuer die
                  spaetere Gameplay-Musik relevant, siehe NOTES.md.
render_wav() nimmt jetzt optional `song_index` entgegen und reicht ihn als
5. CLI-Arg an render_tfmx durch. Der Cache-Dateiname enthaelt den Song-Index
NUR wenn er nicht der Default (0/None) ist, damit bereits vorhandene Caches
fuer Song 0 (z.B. TITEL.wav) gueltig bleiben.
"""
import os
import subprocess
import sys

_HERE = os.path.dirname(os.path.abspath(__file__))
_PLAYER_DIR = os.path.join(_HERE, 'tfmx_player')
_BINARY = os.path.join(_PLAYER_DIR, 'render_tfmx')
_PROJECT_ROOT = os.path.dirname(_HERE)
_CACHE_DIR = os.environ.get('KELLOGG_AUDIO_CACHE', os.path.join(_PROJECT_ROOT, 'audio_cache'))


def _ensure_binary():
    if os.path.exists(_BINARY):
        return
    subprocess.run(['bash', os.path.join(_PLAYER_DIR, 'build.sh')], check=True)


def render_wav(container, name, seconds=180, force=False, song_index=None):
    """container: kellogg_formats.DATContainer; name: z.B. 'TITEL' (ohne Extension).
    song_index: optional -- welcher der ggf. mehreren in <name>.TFX gebuendelten
    Songs gerendert werden soll (siehe Modul-Docstring). None/0 = Default-
    Verhalten wie bisher (erster/einziger Song). Gibt den Pfad zur gerenderten
    (gecachten) WAV-Datei zurueck.

    WICHTIG (Fix 22.07.2026 abends): `seconds` ist nur noch eine Sicherheits-
    OBERGRENZE, keine Ziel-Laenge! render_tfmx erkennt das natuerliche Song-
    Ende/den Loop-Punkt selbst (tfmx.h real_song_end) und schneidet dort ab --
    z.B. ist TITEL (song 0) tatsaechlich ~109s lang, ONGAME2 (song 0) ~123s,
    TITEL2 song0 (Rauser-Sting) nur ~2.04s. Vorher wurde hart bei `seconds`
    abgeschnitten. Der Default hier (180s) ist bewusst grosszuegig ueber die
    laengsten bekannten Stuecke hinaus gewaehlt, damit nichts abgeschnitten
    wird; im Normalfall stoppt render_tfmx laengst vorher von selbst.

    ACHTUNG Cache: der Dateiname ist `<name>.wav` (song_index None/0) bzw.
    `<name>_song<N>.wav` fuer N>0. Wird `seconds` kleiner gewaehlt als die
    echte Songlaenge, MUSS `force=True` gesetzt werden, sonst liefert diese
    Funktion einen ggf. laenger/kuerzer gerenderten alten Cache-Treffer
    zurueck, egal was `seconds` diesmal sagt."""
    os.makedirs(_CACHE_DIR, exist_ok=True)
    suffix = f'_song{song_index}' if song_index else ''
    out_path = os.path.join(_CACHE_DIR, f'{name}{suffix}.wav')
    if os.path.exists(out_path) and not force:
        return out_path
    _ensure_binary()

    tfx_data = container.entries[name + '.TFX']
    sam_data = container.entries[name + '.SAM']
    tfx_path = os.path.join(_CACHE_DIR, f'{name}.TFX')
    sam_path = os.path.join(_CACHE_DIR, f'{name}.SAM')
    with open(tfx_path, 'wb') as f:
        f.write(tfx_data)
    with open(sam_path, 'wb') as f:
        f.write(sam_data)

    cmd = [_BINARY, tfx_path, sam_path, out_path, str(seconds)]
    if song_index:
        cmd.append(str(song_index))
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError(f'render_tfmx failed for {name} (song_index={song_index}): {result.stderr}')
    return out_path


if __name__ == '__main__':
    # Kleiner CLI-Test: python3 tfmx_audio.py <DAT_PATH> <NAME> [seconds] [song_index]
    sys.path.insert(0, _HERE)
    from kellogg_formats import DATContainer
    dat_path = sys.argv[1]
    name = sys.argv[2]
    seconds = int(sys.argv[3]) if len(sys.argv) > 3 else 20
    song_index = int(sys.argv[4]) if len(sys.argv) > 4 else None
    c = DATContainer(dat_path)
    path = render_wav(c, name, seconds, force=True, song_index=song_index)
    print(f'rendered: {path}')
