#pragma once
// guid_diff — the pure, REAPER-free core of the D2 Wave-2 new-content detection.
//
// PURE MODULE (CLAUDE.md §load-bearing split): NO REAPER types, NO SWELL, NO
// vendor/ includes. Standard library only. Unit-tested outside the DAW.
//
// The shell (bank_panel timer) reads REAPER's live track/item GUID set each tick;
// this module owns the DECISION of "which GUIDs are new since the last tick" and the
// first-poll-after-open guard so pre-existing content is never mass-tagged. Keeping
// this here — rather than in the shell — means the fiddly baseline/diff logic is
// unit-tested, mirroring how view_tree splits the folder-depth walk out of view.cpp.
//
// The shell then hands the "new since last tick" GUIDs to the pure autoTagNewContent
// (view_mode_model) to produce the membership writes.

#include <set>
#include <string>
#include <vector>

namespace reasampler {

// The GUIDs present in `current` but absent from `previous` — i.e. new since the
// previous poll. Order is the set's ascending order (deterministic; the caller does
// not depend on discovery order). Empty GUIDs are ignored (a GUID read failure at the
// shell boundary must never be tagged).
std::vector<std::string> newGuids(const std::set<std::string>& previous,
                                  const std::set<std::string>& current);

// Tracks the live GUID set across polls for ONE project, implementing the
// first-poll-after-open guard: the first observation after a (re)start establishes a
// BASELINE and reports NOTHING new, so pre-existing content stays at its default
// (Arrange) rather than being mass-tagged. Every subsequent observe() returns only the
// GUIDs created since the prior observe().
//
// Project switches are handled by reset(): the shell detects a project change (the
// active ReaProject* / project GUID changed) and calls reset() so the next observe()
// re-baselines against the newly-opened project instead of diffing across two
// unrelated projects (which would spuriously "detect" the entire new project as new
// content, or miss content because a same-GUID collision looked pre-existing).
class GuidBaseline {
public:
    // Observes the current live GUID set. On the FIRST call after construction or
    // reset() this records the baseline and returns {} (nothing is "new" at open).
    // On every later call it returns the GUIDs added since the previous call and
    // advances the baseline to `current`. Empty GUIDs are ignored.
    std::vector<std::string> observe(const std::set<std::string>& current);

    // Re-arms the first-poll guard: the next observe() re-baselines and reports
    // nothing new. Called on a project switch so detection never diffs across
    // projects.
    void reset();

    // True until the first observe() after construction/reset — exposed for the shell
    // to reason about (and for tests) about whether a baseline is established yet.
    bool primed() const { return primed_; }

private:
    std::set<std::string> baseline_;
    bool                  primed_ = false;  // false ⇒ next observe() sets the baseline
};

}  // namespace reasampler
