
#ifndef BEATRAT_REGISTER_H
#define BEATRAT_REGISTER_H

#include <X11/Xlib.h>
#include <stddef.h>
#include <stdint.h>

/* Same cap as MAX_TRACKS (track.h) -- a register can hold at most one
 * clip per track (a whole-project region copy stores one slice per
 * track; a track-group copy stores one clip per copied track). */
#define REGISTER_MAX_CLIPS 16

typedef struct {
    char name[64];        /* the source track's name -- empty for a plain region copy with no track identity */
    int16_t *samples;
    size_t num_samples;
    uint32_t sample_rate;
} RegisterClip;

/* Two of these exist in AppContext: the beatrat register (default) and
 * the system register (Shift for normal/emacs-style binds, Super for
 * vim-style binds -- see keybinds.c's defaults). Both are exactly the
 * same shape; "system" only differs in that it also gets opportunistically
 * offered to the X11 CLIPBOARD selection (register_claim_clipboard) so
 * other apps *could* pick it up, best-effort -- Beat Rat itself always
 * pastes from its own copy here, never by round-tripping through X11,
 * so paste stays reliable even if some other app steals clipboard
 * ownership in between. */
typedef struct {
    RegisterClip clips[REGISTER_MAX_CLIPS];
    int num_clips;
    int is_track_copy; /* 1 = whole track(s) (paste appends new tracks); 0 = a region of audio (paste splices in) */
    int valid;         /* 0 = register has never been filled (or was explicitly cleared) -- paste/void is a no-op */
} Register;

/* Frees every clip's sample buffer and resets to empty/invalid. Safe to
 * call on an already-clear register. */
void register_clear(Register *r);

/* Starts a fresh multi-clip fill -- clears whatever was there before,
 * then register_add_clip() is called once per track/slice. Call this
 * even for a single-clip copy (just add one clip after). */
void register_begin(Register *r, int is_track_copy);

/* Takes ownership of `samples` (do not free it yourself afterward, and
 * do not reuse the pointer -- the register may outlive the call that
 * produced it). Silently drops the clip (freeing samples) if the
 * register is already at REGISTER_MAX_CLIPS. */
void register_add_clip(Register *r, const char *name, int16_t *samples,
                        size_t num_samples, uint32_t sample_rate);

/* ---------------------------------------------------------------- */
/* Best-effort X11 CLIPBOARD export (system register only)            */
/* ---------------------------------------------------------------- */

/* Claims CLIPBOARD ownership for `win`. Genuinely serves real audio
 * bytes (as a minimal in-memory WAV) only when the register holds
 * exactly one clip -- a multi-clip copy (a track group, or a
 * whole-project region) has no single well-defined "the audio" to
 * hand another app, so those fall back to the text description only.
 * Most other applications won't ask for our custom target at all
 * (there's no universal "paste audio" convention on X11 the way there
 * is for text), so in practice this is usually just the text fallback
 * -- but it costs nothing to offer the real thing when we can. */
void register_claim_clipboard(Display *dpy, Window win, Atom clipboard_atom,
                               Atom beatrat_audio_atom, const Register *r);

/* Call from the event loop's SelectionRequest case, when the request
 * targets our window (i.e. we still own CLIPBOARD -- check via
 * SelectionClear, or just always call this and let it answer "nothing
 * available" if the register is stale; harmless either way). */
void register_handle_selection_request(Display *dpy, const XSelectionRequestEvent *req,
                                        Atom targets_atom, Atom beatrat_audio_atom,
                                        const Register *system_register);

#endif
