// param_id.cpp — see param_id.h. The table is written out rather than derived: a derived id is
// a function of something else, and every such input then has to never change. A literal table
// makes the freeze visible AT THE POINT OF CHANGE — it cannot be renumbered by accident, because
// renumbering it means editing the numbers.

#include "core/instrument/param/param_id.h"

namespace reasampler::instrument::param {

namespace {

// Within a block the order is the group's own semantic order — envelope stages in temporal
// order, filter cells in solve order — seeded ONCE here and never re-seeded from cellIds. A
// group's cell order is exactly as mobile as the deck's row order is; this sequence is a
// property of THIS table, which is what lets DeckParam keep its "runtime-only, free to change"
// licence.
const std::vector<ParamRow>& table() {
    static const std::vector<ParamRow> kTable = {
        {kParamKeyTrackPitch,       DeckParam::kKeyTrack,          kUnitPitch,     "Key Track",            "KeyTrk"},
        {kParamRate,                DeckParam::kRate,              kUnitPitch,     "Playback Rate",        "Rate"},
        {kParamPitchOffset,         DeckParam::kPitch,             kUnitPitch,     "Pitch Offset",         "Pitch"},

        {kParamPitchEnvAttack,      DeckParam::kPitchEnvAttack,    kUnitPitchEnv,  "Pitch Env Attack",     "PEnvA"},
        {kParamPitchEnvAttackCurve, DeckParam::kPitchEnvAttackCurve, kUnitPitchEnv, "Pitch Env Attack Curve", "PEnvAC"},
        {kParamPitchEnvHold,        DeckParam::kPitchEnvHold,      kUnitPitchEnv,  "Pitch Env Hold",       "PEnvH"},
        {kParamPitchEnvDecay,       DeckParam::kPitchEnvDecay,     kUnitPitchEnv,  "Pitch Env Decay",      "PEnvD"},
        {kParamPitchEnvDecayCurve,  DeckParam::kPitchEnvDecayCurve, kUnitPitchEnv, "Pitch Env Decay Curve", "PEnvDC"},
        {kParamPitchEnvDepth,       DeckParam::kPitchEnvDepth,     kUnitPitchEnv,  "Pitch Env Depth",      "PEnvDp"},

        {kParamFilterMorph,         DeckParam::kFilterMorph,       kUnitFilter,    "Filter Morph",         "Morph"},
        {kParamFilterCutoff,        DeckParam::kFilterCutoff,      kUnitFilter,    "Filter Cutoff",        "Cutoff"},
        {kParamFilterQ,             DeckParam::kFilterQ,           kUnitFilter,    "Filter Q",             "Q"},
        {kParamFilterDrive,         DeckParam::kFilterDrive,       kUnitFilter,    "Filter Drive",         "Drive"},
        {kParamFilterModAmount,     DeckParam::kFilterModAmt,      kUnitFilter,    "Filter Env Amount",    "FEnvAmt"},
        {kParamFilterVelAmount,     DeckParam::kFilterVel,         kUnitFilter,    "Filter Vel Amount",    "FVelAmt"},
        {kParamKeyTrackFilter,      DeckParam::kFilterKeyTrack,    kUnitFilter,    "Filter Key Track",     "FKeyTrk"},

        {kParamFilterEnvAttack,      DeckParam::kFilterEnvAttack,      kUnitFilterEnv, "Filter Env Attack",  "FEnvA"},
        {kParamFilterEnvAttackCurve, DeckParam::kFilterEnvAttackCurve, kUnitFilterEnv, "Filter Env Attack Curve", "FEnvAC"},
        {kParamFilterEnvHold,        DeckParam::kFilterEnvHold,        kUnitFilterEnv, "Filter Env Hold",    "FEnvH"},
        {kParamFilterEnvDecay,       DeckParam::kFilterEnvDecay,       kUnitFilterEnv, "Filter Env Decay",   "FEnvD"},
        {kParamFilterEnvDecayCurve,  DeckParam::kFilterEnvDecayCurve,  kUnitFilterEnv, "Filter Env Decay Curve", "FEnvDC"},
        {kParamFilterEnvSustain,     DeckParam::kFilterEnvSustain,     kUnitFilterEnv, "Filter Env Sustain", "FEnvS"},
        {kParamFilterEnvRelease,     DeckParam::kFilterEnvRelease,     kUnitFilterEnv, "Filter Env Release", "FEnvR"},
        {kParamFilterEnvReleaseCurve, DeckParam::kFilterEnvReleaseCurve, kUnitFilterEnv, "Filter Env Release Curve", "FEnvRC"},
        {kParamFilterTrigAttack,     DeckParam::kFilterTrigAttack,     kUnitFilterEnv, "Filter Trig Attack", "FTrgA"},
        {kParamFilterTrigAttackCurve, DeckParam::kFilterTrigAttackCurve, kUnitFilterEnv, "Filter Trig Attack Curve", "FTrgAC"},
        {kParamFilterTrigHold,       DeckParam::kFilterTrigHold,       kUnitFilterEnv, "Filter Trig Hold",   "FTrgH"},
        {kParamFilterTrigDecay,      DeckParam::kFilterTrigDecay,      kUnitFilterEnv, "Filter Trig Decay",  "FTrgD"},
        {kParamFilterTrigDecayCurve, DeckParam::kFilterTrigDecayCurve, kUnitFilterEnv, "Filter Trig Decay Curve", "FTrgDC"},

        {kParamAmpAttack,           DeckParam::kAttack,            kUnitAmp,       "Amp Attack",           "AmpA"},
        {kParamAmpAttackCurve,      DeckParam::kAttackCurve,       kUnitAmp,       "Amp Attack Curve",     "AmpAC"},
        {kParamAmpHold,             DeckParam::kHold,              kUnitAmp,       "Amp Hold",             "AmpH"},
        {kParamAmpDecay,            DeckParam::kDecay,             kUnitAmp,       "Amp Decay",            "AmpD"},
        {kParamAmpDecayCurve,       DeckParam::kDecayCurve,        kUnitAmp,       "Amp Decay Curve",      "AmpDC"},
        {kParamAmpSustain,          DeckParam::kSustain,           kUnitAmp,       "Amp Sustain",          "AmpS"},
        {kParamAmpRelease,          DeckParam::kRelease,           kUnitAmp,       "Amp Release",          "AmpR"},
        {kParamAmpReleaseCurve,     DeckParam::kReleaseCurve,      kUnitAmp,       "Amp Release Curve",    "AmpRC"},
        {kParamTriggerLength,       DeckParam::kTrigLength,        kUnitAmp,       "Trigger Length",       "TrgLen"},
        {kParamAmpTrigAttack,       DeckParam::kTrigAttack,        kUnitAmp,       "Amp Trig Attack",      "ATrgA"},
        {kParamAmpTrigAttackCurve,  DeckParam::kTrigAttackCurve,   kUnitAmp,       "Amp Trig Attack Curve", "ATrgAC"},
        {kParamAmpTrigHold,         DeckParam::kTrigHold,          kUnitAmp,       "Amp Trig Hold",        "ATrgH"},
        {kParamAmpTrigDecay,        DeckParam::kTrigDecay,         kUnitAmp,       "Amp Trig Decay",       "ATrgD"},
        {kParamAmpTrigDecayCurve,   DeckParam::kTrigDecayCurve,    kUnitAmp,       "Amp Trig Decay Curve", "ATrgDC"},

        {kParamMasterGain,          DeckParam::kMasterGain,        kUnitMaster,    "Master Gain",          "Gain"},
    };
    return kTable;
}

}  // namespace

const std::vector<ParamRow>& paramTable() { return table(); }

bool isExposed(DeckParam deck) {
    return ui::deckParamCommit(deck) != ui::LiveCommit::Reload;
}

const std::vector<ParamRow>& exposedParams() {
    static const std::vector<ParamRow> kExposed = [] {
        std::vector<ParamRow> rows;
        for (const ParamRow& row : table()) {
            if (isExposed(row.deck)) rows.push_back(row);
        }
        return rows;
    }();
    return kExposed;
}

const ParamRow* exposedRowFor(ParamId id) {
    for (const ParamRow& row : exposedParams()) {
        if (row.id == id) return &row;
    }
    return nullptr;
}

ParamId paramIdFor(DeckParam deck) {
    for (const ParamRow& row : table()) {
        if (row.deck == deck) return row.id;
    }
    return 0;
}

}  // namespace reasampler::instrument::param
