#pragma once
// actions — the Design View action family (Phase D4). Registers the bindable
// actions that drive the mode workflow and wires them end-to-end: toggle/activate
// a mode, tag/untag/show-both the current track selection. Each action mutates the
// session's ViewModeModel (D1, via persist's ReaSamplerSession) and then reapplies
// the active mode through the view shell (D2) so the change takes effect immediately.
//
// REAPER-facing shell: the .cpp includes reaper_plugin_functions.h WITHOUT
// REAPERAPI_IMPLEMENT (main.cpp owns the API pointers — CLAUDE.md §contract). This
// header is SDK-free; main.cpp calls register/handle/unregister and nothing else.
//
// Split out of main.cpp (rather than inlined there) to match CONTEXT.md's planned
// `actions` module and keep main.cpp's entrypoint focused on API-pointer ownership
// and lifecycle. The reapply-on-open glue stays in main.cpp (it owns the timer that
// drives persist.poll()); this module only registers and services the actions.

// Forward-declared at GLOBAL scope (matches reaper_plugin.h's typedef struct
// reaper_plugin_info_t) so this header stays SDK-free; the .cpp includes the real
// definition. Declared before the namespace so it is the global type, not a
// namespace-local shadow.
struct reaper_plugin_info_t;

namespace reasampler {

class ReaSamplerSession;

// Registers the Design View action family against `rec` (command_id + gaccel +
// hookcommand-routing is owned by the caller's single hookcommand). `session` is the
// live session the actions mutate; it must outlive the registration. Idempotent is
// NOT promised — call exactly once at load, mirror-unregister once at unload.
void designViewRegisterActions(reaper_plugin_info_t* rec, ReaSamplerSession* session);

// Services one fired command. Returns true iff `command` is one of this module's
// action ids (and it was handled); false otherwise so the caller's hookcommand keeps
// looking (per the contract: claim only our own ids). Safe to call for any command.
bool designViewHandleCommand(int command);

// Mirror-unregisters everything designViewRegisterActions registered, with the
// '-'-prefixed strings (per the contract's unload rule). Call once on rec==nullptr.
void designViewUnregisterActions(reaper_plugin_info_t* rec);

// --- Multi-bank action family (Phase B3) -----------------------------------
// The bindable action set that drives the multi-bank workflow: create / rename /
// delete / evacuate a bank, activate a bank (direct pool/design-free + cycle), move /
// copy the panel's selected samples into a bank, and the two vertical-split
// full-height toggles. Every mutating action drives the B1 model on
// g_session.book() and persists via g_session.saveToActiveProject() so the change
// travels with the .rpp; the toggles flip the B4-rendered layout bit on the panel.
//
// Same registration/routing/unload contract as the Design View family above and the
// same shared g_session. Kept a distinct trio (not folded into the Design View one)
// because the two families are orthogonal pillars — but they share the single
// hookcommand main.cpp owns; each family's Handle claims only its own ids.

// Registers the multi-bank family against `rec`. `session` is the live session (must
// outlive registration). Call exactly once at load. Shares g_session with the Design
// View family — pass the SAME session pointer.
void bankRegisterActions(reaper_plugin_info_t* rec, ReaSamplerSession* session);

// Services one fired command for the multi-bank family. True iff it was one of this
// family's ids (and handled); false otherwise so the caller's hookcommand keeps
// looking. Safe for any command.
bool bankHandleCommand(int command);

// Mirror-unregisters the multi-bank family with '-'-prefixed strings. Call once on
// rec==nullptr (before g_session is torn down).
void bankUnregisterActions(reaper_plugin_info_t* rec);

// The registered command id for the "Prune bank folder" action (Phase R, R3), or 0 before
// registration. The bank_panel prune button fires the action THROUGH this id via
// Main_OnCommand (fork R-E: the button dispatches the command, it does not call the session
// directly) so the panel affordance and the bindable action share one guarded code path.
int bankPruneCommandId();

// Persists a completed bank-index verb as a single REAPER undo point (R-B).
// Wraps persistBook() (= SetProjExtState) in a Begin/End block with UNDO_STATE_MISCCFG
// so the bank op is one Ctrl-Z. On an unsaved / no-active project persistBook() no-ops
// and the block is closed with an empty label + zero flag (REAPER discards it). Callers
// must invoke this ONLY after a successful/effective mutation — rejected ops (duplicate
// name, un-deletable pool, etc.) must return before reaching here so no empty undo
// point is ever opened for a no-op. Defined in actions.cpp alongside persistBook().
//
// S9 bank-generation bump: pass `bumpGeneration = true` for a verb that changes what a live
// instance would PLAY — move / copy / remove / evacuate / delete-with-members (a sample left,
// arrived, or dropped out of a bank an instance may reference). Leave it false (the default)
// for a PURELY ORGANIZATIONAL verb — create / rename / activate / reorder — which changes no
// existing (bankId, sampleId) -> content mapping, so no instance need refresh. The bump (when
// requested) happens INSIDE the block, BEFORE persistBook(), so the stamped counter rides the
// same ext-state write and undo captures the pre/post generation with the rest of the blob.
void persistBankOp(const char* label, bool bumpGeneration = false);

}  // namespace reasampler
