#include "fl/audio/audio_batch.h"
#include "fl/audio/audio_processor.h"

namespace fl {

void AudioBatch::ensurePeaks() const {
    fl::lock_guard<fl::mutex> lock(mMutex);
    if (mPeaksComputed) {
        return;
    }
    for (const AudioFrame &af : mFrames) {
        if (af.bass > mPeaks.bass)
            mPeaks.bass = af.bass;
        if (af.mid > mPeaks.mid)
            mPeaks.mid = af.mid;
        if (af.treble > mPeaks.treble)
            mPeaks.treble = af.treble;
        if (af.volume > mPeaks.volume)
            mPeaks.volume = af.volume;
        mPeaks.beat = mPeaks.beat || af.beat;
    }
    mPeaksComputed = true;
}

const VibeLevels &AudioBatch::vibe() const {
    fl::lock_guard<fl::mutex> lock(mMutex);
    if (!mVibeComputed) {
        if (mProc) {
            mVibe.bass = mProc->getVibeBass();
            mVibe.mid = mProc->getVibeMid();
            mVibe.treb = mProc->getVibeTreb();
            mVibe.vol = mProc->getVibeVol();
            mVibe.bassSpike = mProc->isVibeBassSpike();
            mVibe.midSpike = mProc->isVibeMidSpike();
            mVibe.trebSpike = mProc->isVibeTrebSpike();
        }
        mVibeComputed = true;
    }
    return mVibe;
}

const EqLevels &AudioBatch::equalizer() const {
    fl::lock_guard<fl::mutex> lock(mMutex);
    if (!mEqComputed) {
        if (mProc) {
            mEq.bass = mProc->getEqBass();
            mEq.mid = mProc->getEqMid();
            mEq.treble = mProc->getEqTreble();
            mEq.volume = mProc->getEqVolume();
            mEq.dominantFreqHz = mProc->getEqDominantFreqHz();
            mEq.isSilence = mProc->getEqIsSilence();
            for (int i = 0; i < EqLevels::kNumBins; ++i) {
                mEq.bins[i] = mProc->getEqBin(i);
            }
        }
        mEqComputed = true;
    }
    return mEq;
}

const PercussionState &AudioBatch::percussion() const {
    fl::lock_guard<fl::mutex> lock(mMutex);
    if (!mPercComputed) {
        if (mProc) {
            mPerc.kick = mProc->isKick();
            mPerc.snare = mProc->isSnare();
            mPerc.hihat = mProc->isHiHat();
            mPerc.tom = mProc->isTom();
        }
        mPercComputed = true;
    }
    return mPerc;
}

} // namespace fl
