//
// Platform media controls integration.
//
// Generic API used throughout the codebase. Platform backends live below:
//   Linux  — MPRIS2 via D-Bus (jai-mpris)
//   macOS  — stub (add MPNowPlayingInfoCenter bindings here when needed)
//
// Call sites use media_controls_* unconditionally; the procs no-op on
// platforms with no backend yet.
//

media_controls_init :: () {
    #if OS == .LINUX   _mc_linux_init();
}

media_controls_shutdown :: () {
    #if OS == .LINUX   _mc_linux_shutdown();
}

// Call once per frame from the main loop; dispatches pending D-Bus messages
// and acts on any remote commands (next/prev/play-pause/seek).
media_controls_pump :: () {
    #if OS == .LINUX   _mc_linux_pump();
}

// Call after a new track starts playing.
media_controls_notify_track :: () {
    #if OS == .LINUX   _mc_linux_notify_track();
}

// Call after pause/unpause state changes.
media_controls_notify_status :: () {
    #if OS == .LINUX   _mc_linux_notify_status();
}

// ── Linux / MPRIS2 ───────────────────────────────────────────────────────────

#if OS == .LINUX {

Mpris :: #import "jai-mpris";

#scope_file

_mpris: Mpris.Mpris_Player;

// Flags set by #c_call callbacks, read + cleared in _mc_linux_pump().
_want_play_pause  : bool;
_want_next        : bool;
_want_prev        : bool;
_want_stop        : bool;
_seek_offset_us   : s64;
_seek_pending     : bool;
_set_pos_us       : s64;
_set_pos_pending  : bool;

_cb_play_pause :: (ud: *void) #c_call { _want_play_pause = true; }
_cb_next       :: (ud: *void) #c_call { _want_next       = true; }
_cb_prev       :: (ud: *void) #c_call { _want_prev       = true; }
_cb_stop       :: (ud: *void) #c_call { _want_stop       = true; }
_cb_seek       :: (offset_us: s64, ud: *void) #c_call {
    _seek_offset_us = offset_us;
    _seek_pending   = true;
}
_cb_set_position :: (track_id: *u8, pos_us: s64, ud: *void) #c_call {
    _set_pos_us      = pos_us;
    _set_pos_pending = true;
}

_mc_linux_init :: () {
    _mpris = Mpris.mpris_player_create("CelicaPlayer", "Celica");
    if !_mpris {
        log_warn("media_controls: MPRIS registration failed");
        return;
    }
    Mpris.mpris_on_play_pause  (_mpris, _cb_play_pause,   null);
    Mpris.mpris_on_play        (_mpris, _cb_play_pause,   null);
    Mpris.mpris_on_pause       (_mpris, _cb_play_pause,   null);
    Mpris.mpris_on_next        (_mpris, _cb_next,         null);
    Mpris.mpris_on_previous    (_mpris, _cb_prev,         null);
    Mpris.mpris_on_stop        (_mpris, _cb_stop,         null);
    Mpris.mpris_on_seek        (_mpris, _cb_seek,         null);
    Mpris.mpris_on_set_position(_mpris, _cb_set_position, null);

    Mpris.mpris_set_can_play       (_mpris, true);
    Mpris.mpris_set_can_pause      (_mpris, true);
    Mpris.mpris_set_can_go_next    (_mpris, true);
    Mpris.mpris_set_can_go_previous(_mpris, true);
    Mpris.mpris_set_can_seek       (_mpris, true);
    Mpris.mpris_set_playback_status(_mpris, "Stopped");
    log_info("media_controls: MPRIS registered as org.mpris.MediaPlayer2.CelicaPlayer");
}

_mc_linux_shutdown :: () {
    if !_mpris  return;
    Mpris.mpris_player_destroy(_mpris);
    _mpris = null;
}

_mc_linux_pump :: () {
    if !_mpris  return;

    Mpris.mpris_process(_mpris);

    if _want_play_pause {
        _want_play_pause = false;
        audio_toggle_pause();
        _mc_linux_notify_status();
    }
    if _want_next { _want_next = false; queue_next(); }
    if _want_prev { _want_prev = false; queue_prev(); }
    if _want_stop {
        _want_stop = false;
        stop_current_stream();
        Mpris.mpris_set_playback_status(_mpris, "Stopped");
    }
    if _seek_pending {
        _seek_pending = false;
        if app.current_stream && app.current_stream.sound_data {
            rate   := cast(float64) app.current_stream.sound_data.sampling_rate;
            cur_us := cast(s64)(app.current_stream.play_cursor / rate * 1_000_000.0);
            audio_seek_seconds(cast(float)(cur_us + _seek_offset_us) / 1_000_000.0);
        }
    }
    if _set_pos_pending {
        _set_pos_pending = false;
        audio_seek_seconds(cast(float) _set_pos_us / 1_000_000.0);
    }

    // Keep MPRIS playhead in sync every frame.
    if app.current_stream && app.current_stream.sound_data {
        rate   := cast(float64) app.current_stream.sound_data.sampling_rate;
        pos_us := cast(s64)(app.current_stream.play_cursor / rate * 1_000_000.0);
        Mpris.mpris_set_position(_mpris, pos_us);
    }
}

_mc_linux_notify_track :: () {
    if !_mpris  return;
    meta: Mpris.Mpris_Metadata;
    meta.title     = app.current_track.name;
    meta.artist    = app.current_track.artist;
    meta.album     = app.current_track.album;
    // Jellyfin duration_ticks are 100-ns intervals; MPRIS wants microseconds.
    meta.length_us = app.current_track.duration_ticks / 10;
    Mpris.mpris_set_metadata(_mpris, meta);
    Mpris.mpris_set_playback_status(_mpris, "Playing");
}

_mc_linux_notify_status :: () {
    if !_mpris  return;
    Mpris.mpris_set_playback_status(_mpris, ifx app.paused then "Paused" else "Playing");
}

} // #if OS == .LINUX
