#pragma once

#include "IR_config.h"
#include "IrTxBsrrWave.h"

class IrTxIsrBufferedStorageBase {
public:
    IrTxGateRun* gateRuns = nullptr;
    size_t maxGateRuns = 0;
    uint32_t* bsrrWords = nullptr;
    uint16_t wordCount = 0;

    IrTxBsrrWave wave{};
    uint16_t readIdx = 0;
    uint16_t halfLen = 0;
    uint32_t totalTicks = 0;
    uint32_t ticksSent = 0;

    bool isValid() const {
        return gateRuns != nullptr &&
               maxGateRuns != 0U &&
               bsrrWords != nullptr &&
               wordCount >= 2U &&
               (wordCount & 1U) == 0U;
    }

    void resetRuntimeState() {
        readIdx = 0;
        halfLen = static_cast<uint16_t>(wordCount / 2U);
        totalTicks = 0;
        ticksSent = 0;
    }
};

class IrTxIsrBufferedStorageView : public IrTxIsrBufferedStorageBase {
public:
    IrTxIsrBufferedStorageView(IrTxGateRun* runs, size_t runCount, uint32_t* words, uint16_t wordsCount) {
        gateRuns = runs;
        maxGateRuns = runCount;
        bsrrWords = words;
        wordCount = wordsCount;
        resetRuntimeState();
    }
};

template<size_t MaxGateRuns = irproto::kIsrTxMaxGateRuns, uint16_t WordCount = irproto::kIsrTxBsrrWordCount>
class IrTxIsrBufferedStorage : public IrTxIsrBufferedStorageBase {
    static_assert(MaxGateRuns > 0U, "IrTxIsrBufferedStorage: MaxGateRuns > 0");
    static_assert(WordCount >= 2U, "IrTxIsrBufferedStorage: WordCount >= 2");
    static_assert((WordCount & 1U) == 0U, "IrTxIsrBufferedStorage: WordCount must be even");

public:
    IrTxIsrBufferedStorage() {
        gateRuns = gateRunsStorage_;
        maxGateRuns = MaxGateRuns;
        bsrrWords = bsrrWordsStorage_;
        wordCount = WordCount;
        resetRuntimeState();
    }

private:
    IrTxGateRun gateRunsStorage_[MaxGateRuns]{};
    uint32_t bsrrWordsStorage_[WordCount]{};
};
