#include "rive/audio/audio_source.hpp"
#ifdef WITH_RIVE_AUDIO
#include "rive/audio/audio_engine.hpp"
#include "rive/audio/audio_sound.hpp"
#include "rive/audio/audio_reader.hpp"
#include "rive/audio/audio_reader.hpp"
#endif

using namespace rive;

#ifdef WITH_RIVE_AUDIO
// Both of these should be make_rcp but it is currently getting refed directy
// somewhere else so until we refactor that we have to not ref here.
rcp<AudioSource> AudioSource::MakeAudioSource(rive::Span<uint8_t> fileBytes)
{
    ma_decoder decoder;
    ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 0, 0);
    if (ma_decoder_init_memory(fileBytes.data(),
                               fileBytes.size(),
                               &config,
                               &decoder) != MA_SUCCESS)
    {
        return nullptr;
    }
    ma_decoder_uninit(&decoder);
    return rcp<AudioSource>(new AudioSource(std::move(fileBytes)));
}

rcp<AudioSource> AudioSource::MakeAudioSource(
    rive::SimpleArray<uint8_t> fileBytes)
{
    ma_decoder decoder;
    ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 0, 0);
    auto result = ma_decoder_init_memory(fileBytes.data(),
                                         fileBytes.size(),
                                         &config,
                                         &decoder);
    if (result != MA_SUCCESS)
    {
        fprintf(stderr,
                "Failed to decode audio with error %s\n",
                ma_result_description(result));
        return nullptr;
    }

    ma_decoder_uninit(&decoder);
    return rcp<AudioSource>(new AudioSource(std::move(fileBytes)));
}

AudioSource::AudioSource(rive::Span<float> samples,
                         uint32_t numChannels,
                         uint32_t sampleRate) :
    m_isBuffered(true),
    m_channels(numChannels),
    m_sampleRate(sampleRate),
    m_duration(-1.0f),
    m_ownedBytes((uint8_t*)samples.data(), samples.size() * sizeof(float))
{
    assert(numChannels != 0);
    assert(sampleRate != 0);
}

AudioSource::AudioSource(rive::Span<uint8_t> fileBytes) :
    m_isBuffered(false),
    m_channels(0),
    m_sampleRate(0),
    m_duration(-1.0f),
    m_fileBytes(fileBytes)
{}

AudioSource::AudioSource(rive::SimpleArray<uint8_t> fileBytes) :
    m_isBuffered(false),
    m_channels(0),
    m_sampleRate(0),
    m_duration(-1.0f),
    m_fileBytes(fileBytes.data(), fileBytes.size()),
    m_ownedBytes(std::move(fileBytes))
{}

const rive::Span<float> AudioSource::bufferedSamples() const
{
    assert(m_isBuffered);
    return rive::Span<float>((float*)m_ownedBytes.data(),
                             m_ownedBytes.size() / sizeof(float));
}

class AudioSourceDecoder
{
public:
    AudioSourceDecoder(rive::Span<uint8_t> fileBytes) : m_decoder({})
    {
        ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 0, 0);
        if (ma_decoder_init_memory(fileBytes.data(),
                                   fileBytes.size(),
                                   &config,
                                   &m_decoder) != MA_SUCCESS)
        {
            fprintf(stderr,
                    "AudioSourceDecoder - Failed to initialize decoder.\n");
        }
    }

    ~AudioSourceDecoder() { ma_decoder_uninit(&m_decoder); }

    uint32_t channels() { return (uint32_t)m_decoder.outputChannels; }

    uint32_t sampleRate() { return (uint32_t)m_decoder.outputSampleRate; }

    uint64_t lengthInFrames()
    {
        ma_uint64 length;
        if (ma_data_source_get_length_in_pcm_frames(&m_decoder, &length) !=
            MA_SUCCESS)
        {
            return 0;
        }
        return (uint64_t)length;
    }

private:
    ma_decoder m_decoder;
};

uint32_t AudioSource::channels()
{
    if (m_channels != 0)
    {
        return m_channels;
    }
    AudioSourceDecoder audioDecoder(m_fileBytes);
    return m_channels = audioDecoder.channels();
}

uint32_t AudioSource::sampleRate()
{
    if (m_sampleRate != 0)
    {
        return m_sampleRate;
    }
    AudioSourceDecoder audioDecoder(m_fileBytes);
    return m_sampleRate = audioDecoder.sampleRate();
}

float AudioSource::duration()
{
    if (m_duration >= 0.0f)
    {
        return m_duration;
    }
    if (m_isBuffered)
    {
        uint32_t ch = channels();
        uint32_t sr = sampleRate();
        if (ch == 0 || sr == 0)
        {
            return m_duration = 0.0f;
        }
        return m_duration = (float)bufferedSamples().size() / (float)(ch * sr);
    }
    AudioSourceDecoder audioDecoder(m_fileBytes);
    uint32_t sr = audioDecoder.sampleRate();
    if (sr == 0)
    {
        return m_duration = 0.0f;
    }
    return m_duration = (float)audioDecoder.lengthInFrames() / (float)sr;
}

AudioFormat AudioSource::format() const
{
    if (m_isBuffered)
    {
        return AudioFormat::buffered;
    }
    ma_decoder decoder;
    ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 0, 0);
    if (ma_decoder_init_memory(m_fileBytes.data(),
                               m_fileBytes.size(),
                               &config,
                               &decoder) != MA_SUCCESS)
    {
        fprintf(stderr,
                "AudioSource::format - Failed to initialize decoder.\n");
        return AudioFormat::unknown;
    }
    ma_encoding_format encodingFormat;

    AudioFormat format = AudioFormat::unknown;
    if (ma_decoder_get_encoding_format(&decoder, &encodingFormat) == MA_SUCCESS)
    {
        switch (encodingFormat)
        {
            case ma_encoding_format_mp3:
                format = AudioFormat::mp3;
                break;
            case ma_encoding_format_wav:
                format = AudioFormat::wav;
                break;
            case ma_encoding_format_vorbis:
                format = AudioFormat::vorbis;
                break;
            case ma_encoding_format_flac:
                format = AudioFormat::flac;
                break;
            default:
                format = AudioFormat::unknown;
                break;
        }
    }

    ma_decoder_uninit(&decoder);

    return format;
}

rcp<AudioReader> AudioSource::makeReader(uint32_t numChannels,
                                         uint32_t sampleRate)
{
    if (m_isBuffered)
    {
        return nullptr;
    }

    rive::rcp<rive::AudioSource> rcSource = rive::rcp<rive::AudioSource>(this);
    rcSource->ref();
    auto reader = rcp<AudioReader>(new AudioReader(rcSource, numChannels));

    ma_decoder_config config =
        ma_decoder_config_init(ma_format_f32, numChannels, sampleRate);

    if (ma_decoder_init_memory(m_fileBytes.data(),
                               m_fileBytes.size(),
                               &config,
                               reader->decoder()) != MA_SUCCESS)
    {
        fprintf(stderr,
                "AudioSource::makeReader - Failed to initialize decoder.\n");
        return nullptr;
    }

    return reader;
}
#else
rcp<AudioSource> AudioSource::MakeAudioSource(rive::Span<uint8_t> fileBytes)
{
    return nullptr;
}

rcp<AudioSource> AudioSource::MakeAudioSource(
    rive::SimpleArray<uint8_t> fileBytes)
{
    return nullptr;
}
AudioSource::AudioSource(rive::Span<uint8_t> fileBytes) {}
AudioSource::AudioSource(rive::SimpleArray<uint8_t> fileBytes) {}
AudioSource::AudioSource(rive::Span<float> samples,
                         uint32_t numChannels,
                         uint32_t sampleRate)
{}
uint32_t AudioSource::channels() { return 0; }
uint32_t AudioSource::sampleRate() { return 0; }
AudioFormat AudioSource::format() const { return AudioFormat::unknown; }
const rive::Span<float> AudioSource::bufferedSamples() const
{
    return rive::Span<float>(nullptr, 0);
}
#endif