//
//  AudioGraphResampler.hpp
//  SwitchboardSDK
//
//  Created by Balazs Kiss on 2025. 04. 15..
//

#pragma once

#include <audio/ResamplingFIFO.hpp>
#include <buffer/AudioData.hpp>
#include <functional>
#include <memory>
#include <switchboard/export.h>
#include <switchboard_core/AudioBusList.hpp>

namespace switchboard {

/**
 * @brief AudioGraphResampler class.
 * @details This class is responsible for providing a constant sample rate and buffer size for the audio graph.
 */
class SWITCHBOARDSDK_EXPORT AudioGraphResampler {
public:
    /**
     * @brief Callback function type for processing audio data.
     * 
     * @param inAudioBuses The input audio buses.
     * @param outAudioBuses The output audio buses.
     * 
     * @returns True if the processing was successful, false otherwise.
     */
    using ProcessCallback = std::function<bool(AudioBusList& inAudioBuses, AudioBusList& outAudioBuses)>;

    /**
     * @brief Constructor for AudioGraphResampler.
     * 
     * @param sampleRate The fixed processing sample rate to be used in the callback.
     * @param bufferSize The fixed processing buffer size to be used in the callback.
     */
    AudioGraphResampler(int sampleRate, int bufferSize);

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

    /**
     * @brief Sets the process callback function.
     * 
     * @param callback The process callback function.
     */
    void setProcessCallback(ProcessCallback callback);

    /**
     * @brief Sets the number of input and output buses.
     * 
     * @param numberOfInputBuses The number of input buses.
     * @param numberOfOutputBuses The number of output buses.
     * 
     * @returns True if the operation was successful, false otherwise.
     */
    bool setNumberOfBuses(const uint numberOfInputBuses, const uint numberOfOutputBuses);

    /**
     * @brief Processes the audio data.
     * 
     * @param inAudioBuses The input audio buses.
     * @param outAudioBuses The output audio buses.
     * 
     * @returns True if the processing was successful, false otherwise.
     */
    bool process(AudioBusList& inAudioBuses, AudioBusList& outAudioBuses);

private:
    ProcessCallback processCallback;
    int sampleRate;
    int bufferSize;
    int numberOfInputBuses;
    int numberOfOutputBuses;
    std::unique_ptr<audio::ResamplingFIFO> inputResamplingFIFO;
    std::unique_ptr<audio::ResamplingFIFO> outputResamplingFIFO;
    buffer::AudioData<float> interleavedData;
    buffer::AudioData<float> callbackInAudioData;
    buffer::AudioData<float> callbackOutAudioData;

    bool callProcessCallback(AudioBuffer<float>* inBuffer, AudioBuffer<float>* outBuffer);
    void configureResamplers(AudioBuffer<float>* inBuffer, AudioBuffer<float>* outBuffer);
    bool process(AudioBuffer<float>* inBuffer, AudioBuffer<float>* outBuffer);
    void pushInputBufferToResampler(AudioBuffer<float>& buffer);
    void popInputBufferFromResampler(AudioBuffer<float>& buffer);
    void pushOutputBufferToResampler(AudioBuffer<float>& buffer);
    void popOutputBufferFromResampler(AudioBuffer<float>& buffer);
};

}
