// solo_cache — pure implementation. See solo_cache.h.

#include "core/view/solo_cache.h"

namespace reasampler::view {

std::map<std::string, int> soloedTracks(const std::vector<TrackSolo>& live) {
    std::map<std::string, int> soloed;
    for (const TrackSolo& t : live) {
        if (t.guid.empty() || t.solo == 0) continue;
        soloed.emplace(t.guid, t.solo);  // first reading wins if a GUID repeats
    }
    return soloed;
}

bool SoloCache::store(const std::string& modeId, const std::map<std::string, int>& soloed) {
    if (modeId.empty()) return false;
    if (soloed.empty()) {
        byMode_.erase(modeId);
        return true;
    }
    byMode_[modeId] = soloed;
    return true;
}

const std::map<std::string, int>* SoloCache::query(const std::string& modeId) const {
    auto it = byMode_.find(modeId);
    return it == byMode_.end() ? nullptr : &it->second;
}

bool SoloCache::clear(const std::string& modeId) {
    return byMode_.erase(modeId) > 0;
}

std::size_t SoloCache::reconcile(const std::set<std::string>& liveGuids) {
    std::size_t removed = 0;
    for (auto mode = byMode_.begin(); mode != byMode_.end();) {
        for (auto entry = mode->second.begin(); entry != mode->second.end();) {
            if (liveGuids.count(entry->first) == 0) {
                entry = mode->second.erase(entry);
                ++removed;
            } else {
                ++entry;
            }
        }
        // A mode emptied by pruning must not survive as an empty record — same
        // reason store() drops one (see header).
        if (mode->second.empty()) mode = byMode_.erase(mode);
        else                      ++mode;
    }
    return removed;
}

std::vector<SoloOp> planSoloRestore(const std::map<std::string, int>& cached,
                                    const std::set<std::string>& liveGuids,
                                    const std::set<std::string>& visibleGuids) {
    std::vector<SoloOp> ops;
    for (const auto& [guid, value] : cached) {
        if (liveGuids.count(guid) == 0) continue;
        if (visibleGuids.count(guid) == 0) continue;
        ops.push_back(SoloOp{guid, value});
    }
    return ops;
}

} // namespace reasampler::view
