//
//  ResamplingFIFO.hpp
//  SwitchboardSDK
//
//  Created by Balazs Kiss on 2025. 04. 18..
//

#pragma once

#include <memory>

namespace switchboard::audio {

/**
 * @brief Resampling class for audio streams that uses a FIFO buffer to store the resampled frames.
 */
class ResamplingFIFO {
public:
    /**
     * @brief Constructor for ResamplingFIFO.
     * @param numberOfChannels The channel count of the audio stream. Cannot change after creation.
     * @param maxNumberOfFrames The maximum number of frames that can be stored in the FIFO buffer to store the output frames.
     */
    ResamplingFIFO(int numberOfChannels, int maxNumberOfFrames);

    /**
     * @brief Destructor for ResamplingFIFO.
     */
    ~ResamplingFIFO();

    /**
     * @brief Gets the number of channels.
     * 
     * @return The number of channels.
     */
    int getNumberOfChannels() const;

    /**
     * @brief Gets the maximum number of frames that can be stored in the FIFO buffer.
     * 
     * @return The maximum number of frames.
     */
    int getMaxNumberOfFrames() const;

    /**
     * @brief Gets the input sample rate.
     * 
     * @return The input sample rate.
     */
    int getInputSampleRate() const;

    /**
     * @brief Gets the output sample rate.
     * 
     * @return The output sample rate.
     */
    int getOutputSampleRate() const;

    /**
     * @brief Sets the input and output sample rates that is used for resampling.
     * 
     * @param inputSampleRate The input sample rate.
     * @param outputSampleRate The output sample rate.
     */
    void setRatio(int inputSampleRate, int outputSampleRate);

    /**
     * @brief Pushes audio into the resampler and puts the resampled frames into the FIFO buffer.
     * 
     * @param buffer The input audio buffer.
     * @param numFrames The number of frames in the input buffer.
     * 
     * @return The number of frames that were used from the input buffer.
     * 
     * @details The returned value can indicate a problem when the output buffer is full.
     */
    long pushBuffer(const float* buffer, int numFrames);

    /**
     * @brief Gets the number of frames that are ready to be popped from the FIFO buffer.
     *
     * @return The number of frames ready to be popped.
     */
    int getNumberOfFramesReady() const;

    /**
     * @brief Pops audio from the FIFO buffer.
     * @details Before pulling audio from the FIFO buffer, check if there are enough frames ready to be popped with the `getNumberOfFramesReady` call.
     *
     * @param buffer The output audio buffer.
     * @param numFrames The number of frames to pop.
     */
    void popBuffer(float* buffer, int numFrames);

    /**
     * @brief Resets the internal state of the resampling FIFO.
     */
    void reset();

private:
    struct Impl;
    std::unique_ptr<Impl> pImpl;
};

}
