#pragma once
// action_registry — shared REAPER registration plumbing, plus a data-driven action
// table (ActionTableRow) so adding an action means adding one row, not touching
// register/dispatch/unregister separately (OCP). Interned command-id/label strings
// persist for the module lifetime: REAPER holds those pointers, and an unregister
// must re-present the SAME one. Handlers are flat function pointers, never
// std::function/virtual (hot-path-adjacent dispatch discipline).

#include <cstddef>

#include "reaper_plugin.h"  // reaper_plugin_info_t, gaccel_register_t

namespace reasampler {

// Interns the channel-qualified command id for `suffix` once per process, so a
// '-command_id' unregister presents the IDENTICAL pointer registered earlier.
const char* channelIdFor(const char* suffix);

// Mints a command id from `suffix`, registers its gaccel with label `phrase`.
// Returns the id (0 on failure); gaccel storage is caller-owned.
int registerAction(reaper_plugin_info_t* rec, const char* suffix,
                   gaccel_register_t& accel, const char* phrase);

// --- The registration table ---------------------------------------------------

// `suffix`/`phrase` are channel-agnostic and must have static storage duration.
// `arg` is an opaque per-row value so sibling actions can share one handler.
struct ActionTableRow {
    const char* suffix;    // FOREVER-STABLE command-id suffix — never change shipped
    const char* phrase;    // Actions-list display phrase (after the channel prefix)
    void (*run)(int arg);  // handler — a flat function pointer, no state
    int arg = 0;           // opaque per-row handler argument
};

// Rows are copied into registry-owned storage whose addresses never move (REAPER
// holds each gaccel pointer until unload).
void registerActionTable(reaper_plugin_info_t* rec, const ActionTableRow* rows,
                         std::size_t count);

bool actionTableHandleCommand(int command);

// 0 when unregistered / mint failed — for callers needing a raw id outside dispatch
// (e.g. the toggleaction checked-state hook).
int actionTableCommandId(const char* suffix);

// Mirror-unregisters every table row (reverse order): '-gaccel' with the held
// storage, '-command_id' with the SAME interned pointer used at register.
void unregisterActionTable(reaper_plugin_info_t* rec);

}  // namespace reasampler
