// See view_solo.h. Compiled into the reaper_reasampler module; includes
// reaper_plugin_functions.h without REAPERAPI_IMPLEMENT (main.cpp owns that).

#include "shell/view/view_solo.h"

#include <map>

#define REAPERAPI_MINIMAL
#define REAPERAPI_WANT_GetMediaTrackInfo_Value
#define REAPERAPI_WANT_SetMediaTrackInfo_Value
#include "reaper_plugin_functions.h"

namespace reasampler {

namespace {
// SDK: int, 0=not soloed, 1=soloed, 2=soloed in place, 5=safe soloed,
// 6=safe soloed in place. Documented under SetMediaTrackInfo_Value with no
// read-only marker (unlike B_RECMON_IN_EFFECT in the same list), so it is settable.
constexpr const char* kSoloParm = "I_SOLO";
}  // namespace

std::vector<view::TrackSolo> readTrackSolos(const TrackHandles& handles) {
    std::vector<view::TrackSolo> live;
    live.reserve(handles.size());
    for (const auto& [guid, tr] : handles) {
        if (!tr) continue;
        live.push_back(view::TrackSolo{
            guid, static_cast<int>(GetMediaTrackInfo_Value(tr, kSoloParm))});
    }
    return live;
}

void applySoloOps(const TrackHandles& handles, const std::vector<view::SoloOp>& ops) {
    if (ops.empty()) return;  // the common case: nothing soloed, no project write

    std::map<std::string, int> byGuid;
    for (const view::SoloOp& op : ops) byGuid[op.guid] = op.value;

    for (const auto& [guid, tr] : handles) {
        if (!tr) continue;
        auto it = byGuid.find(guid);
        if (it == byGuid.end()) continue;
        SetMediaTrackInfo_Value(tr, kSoloParm, static_cast<double>(it->second));
    }
}

void clearTrackSolos(const TrackHandles& handles, const std::map<std::string, int>& soloed) {
    std::vector<view::SoloOp> ops;
    ops.reserve(soloed.size());
    for (const auto& entry : soloed) ops.push_back(view::SoloOp{entry.first, 0});
    applySoloOps(handles, ops);
}

void restoreTrackSolos(const TrackHandles& handles,
                       const std::map<std::string, int>& cached,
                       const std::set<std::string>& liveGuids,
                       const std::set<std::string>& visibleGuids) {
    applySoloOps(handles, view::planSoloRestore(cached, liveGuids, visibleGuids));
}

} // namespace reasampler
