#include "Audio.h"

#define MINIAUDIO_IMPLEMENTATION
#include <miniaudio/miniaudio.h>

#include <iostream>
#include <filesystem>

void Audio::data_callback(ma_device *device, void *output, const void *input, ma_uint32 frame_count)
{
    DecoderState* decoder = (DecoderState*)device->pUserData;
    if(decoder == NULL) {
        std::cout << "could not find suitable decoder\n";
        return;
    }

    ma_result result = ma_decoder_read_pcm_frames(&decoder->decoder, output, frame_count, NULL);
    decoder->is_finished = false;
    if (result == MA_AT_END) {
        std::cout << "end of the song... next.\n";
        decoder->is_finished = true;
    }
}

Audio::Audio()
{

    m_device_config = ma_device_config_init(ma_device_type_playback);
    m_device_config.dataCallback = data_callback;
}

Audio::~Audio()
{
    ma_device_uninit(&m_device);
    ma_decoder_uninit(&m_decoder.decoder);
    return;
}

void Audio::load_file(std::filesystem::path file_path)
{
    m_loaded_files.push_back(file_path);
    std::cout << "Loaded file: " << file_path.string() << "\n";

}


void Audio::play()
{
    if (is_playing()) {
        stop();
    }
       

    m_selected_file = m_loaded_files[m_selected_file_idx];

    ma_result result = ma_decoder_init_file(m_selected_file.string().c_str(), NULL, &m_decoder.decoder);
    if (result != MA_SUCCESS) {
        std::cout << "could not load file: " << m_selected_file.string().c_str() << "\n";
        return;
    }

    m_device_config.playback.format = m_decoder.decoder.outputFormat;
    m_device_config.playback.channels = m_decoder.decoder.outputChannels;
    m_device_config.sampleRate = m_decoder.decoder.outputSampleRate;
    m_device_config.pUserData = &m_decoder;

    if (ma_device_init(NULL, &m_device_config, &m_device) != MA_SUCCESS) {
        std::cout << "failed to open playback device.\n";
        return;
    }

    if (ma_device_start(&m_device) != MA_SUCCESS) {
        std::cout << "could not start playback device" << "\n";
        return;
    }

    m_is_playing = true;
}

void Audio::stop()
{
    if (is_playing()) {
        ma_device_uninit(&m_device);
        ma_decoder_uninit(&m_decoder.decoder);
        m_is_playing = false;
    }
}

void Audio::select_file(std::filesystem::path file)
{
    
    for (size_t i = 0; i < m_loaded_files.size(); i++) {
        if (file == m_loaded_files[i]) {
            m_selected_file = file;
            m_selected_file_idx = i;
        }
    }
    //m_select_file_idx = m_loaded_files
}

void Audio::next_music()
{
    m_selected_file_idx += 1;
    if (m_loaded_files.size() <= m_selected_file_idx) {
        m_selected_file_idx = 0;
    }

    if (is_playing())
        play();
}

std::vector<std::filesystem::path> Audio::loaded_files()
{
    return m_loaded_files;
}
