#pragma once
// insert_plan — the REAPER-free logic behind the `insert` shell: computing the
// InsertMedia `mode` bitmask from a small options struct.
//
// PURE MODULE: NO REAPER types, NO SWELL, NO vendor/ includes. Standard library
// only. The InsertMedia bitfield is easy to get wrong and its bits are
// load-bearing for the "no silent time-stretch" invariant, so it's factored here
// and unit-tested. The REAPER-bound placement (InsertMedia call, edit-cursor
// movement, undo block) lives in insert.cpp and is DAW-verified.
//
// Bit meanings below are transcribed VERBATIM from the authoritative header
// doc-comment (vendor/reaper-sdk/sdk/reaper_plugin_functions.h, InsertMedia):
//   mode: 0=add to current track, 1=add new track, 3=add to selected items as
//   takes, &4=stretch/loop to fit time sel, &8=try to match tempo 1x,
//   &16=try to match tempo 0.5x, &32=try to match tempo 2x,
//   &64=don't preserve pitch when matching tempo, ...
// We use only the base target (0/1) and the tempo-conform bits (&8/&16/&32/&64).
// We NEVER set &4 (stretch/loop to fit time selection) — the silent-time-stretch
// path the tool forbids.

#include <cstdint>

namespace reasampler::capture {

// Where InsertMedia drops the item. Maps to the low bits of `mode` (mode&3).
// We expose only the two placement targets needed here; "add as takes" (3) is
// out of scope. Both insert at the edit cursor — REAPER's convention for base
// modes 0/1 (the header names no explicit edit-cursor bit; see the flagged
// runtime assumption in insert.cpp).
enum class InsertTarget {
    NewTrack,       // mode base 1: add a new track for the item
    CurrentTrack,   // mode base 0: add to the current/selected track
};

// Tempo-conform choice. Default is None: insert at the file's native length with
// NO stretching (the precision-preserving default). The three ratios are the
// explicit opt-in "try to match project tempo" paths — never applied silently.
// Ratio1x is the ordinary "conform to tempo"; Half/Double are the octave-shifted
// variants REAPER exposes for half/double-time material.
enum class TempoConform {
    None,     // no tempo bits set: native length, no stretch (default)
    Ratio1x,  // &8:  try to match tempo 1x
    RatioHalf,// &16: try to match tempo 0.5x
    RatioDouble,// &32: try to match tempo 2x
};

// Options that shape one InsertMedia call. Defaults encode the intended path:
// current track (user's selection), no conform, pitch preserved.
struct InsertOptions {
    InsertTarget target = InsertTarget::CurrentTrack;
    TempoConform conform = TempoConform::None;

    // Only meaningful when conform != None. When false, adds &64 ("don't preserve
    // pitch when matching tempo") so a tempo match also shifts pitch (classic
    // varispeed). Default true = preserve pitch across the tempo match. Ignored
    // when conform == None (no tempo bits set, so pitch is moot).
    bool preservePitch = true;
};

// Computes the InsertMedia `mode` integer for the given options.
//
// Guarantees enforced here (and asserted in tests):
//   * The &4 stretch-to-time-selection bit is NEVER set (no silent stretch).
//   * When conform == None, NONE of the tempo bits (&8/&16/&32/&64) are set — the
//     item lands at native length.
//   * Exactly one base target bit pattern is used (0 or 1), never 3.
int computeInsertMode(const InsertOptions& opts);

// The forbidden stretch bit, exposed so a test can assert it is never present in
// any computed mode (the "no silent time-stretch" invariant, made checkable).
inline constexpr int kStretchToTimeSelBit = 4;

} // namespace reasampler::capture
