// loop_marks.cpp — see loop_marks.h. Pure value folds; no host types.

#include "core/instrument/ui/loop_marks.h"

#include "core/instrument/engine/loop/loop_span.h"  // defaultLoopBounds

namespace reasampler::instrument::ui {

namespace {

// The engine's own acceptance test, restated over the editor's two integers: resolveLoop
// refuses an inverted, empty or out-of-range span rather than repairing it, so a span it would
// refuse is one the handles must be re-parked out of.
bool spanUsable(std::int64_t loopStart, std::int64_t loopEnd, std::int64_t frameCount) {
    return loopStart >= 0 && loopEnd > loopStart && loopEnd <= frameCount;
}

}  // namespace

LoopMarks resolveLoopMarks(const StoredLoop& stored, std::int64_t frameCount) {
    LoopMarks m;
    if (stored.override_) {
        m.hasLoop = stored.override_->hasLoop;
        m.loopStart = stored.override_->start;
        m.loopEnd = stored.override_->end;
    } else if (stored.intrinsic && stored.intrinsic->hasLoop) {
        m.hasLoop = true;
        m.loopStart = stored.intrinsic->start;
        m.loopEnd = stored.intrinsic->end;
    }
    if (stored.startPoint) m.start = *stored.startPoint;
    m.crossfade = stored.crossfade > 0 ? stored.crossfade : 0;

    if (!spanUsable(m.loopStart, m.loopEnd, frameCount)) {
        m.hasLoop = false;
        m.parked = true;
        const engine::loop::LoopBounds d = engine::loop::defaultLoopBounds(frameCount);
        m.loopStart = d.start;
        m.loopEnd = d.end;
    }
    return m;
}

LoopWrite applyLoopMarks(const LoopMarks& m) {
    LoopWrite w;
    const bool spanAlive = m.loopEnd > m.loopStart;
    w.loop.hasLoop = m.hasLoop && spanAlive;
    if (m.parked && !m.hasLoop) {
        // A parked pair (never set) must round-trip back to parked, not to a real "LOOP OFF"
        // span — resolveLoopMarks only re-parks a span spanUsable would refuse, so collapse it
        // deliberately rather than writing back the default bounds' own alive span.
        w.loop.start = m.loopStart;
        w.loop.end = m.loopStart;
    } else {
        w.loop.start = m.loopStart;
        w.loop.end = m.loopEnd;
    }
    w.crossfade = (spanAlive && m.crossfade > 0) ? m.crossfade : 0;
    w.start = m.start;
    return w;
}

}  // namespace reasampler::instrument::ui
