#include "AudioWriter.h"

#include "File.h"
#include "BinaryStream.h"
#include "AudioSample.h"
#include "FileLogger.h"

AudioWriter::AudioWriter()
{

}

void AudioWriter::setPath(const Path& path)
{
    mPath = path;
}

bool AudioWriter::write(const AudioSamplePtr& sample)
{
    if (mPath.empty())
    {
        MLOG_ERROR("Attempted to write audio with no output file path, aborting Write.");
        return false;
    }

    File outfile(mPath);
    if (!outfile.open(File::AccessMode::Write))
    {
        MLOG_ERROR("Failed to open audio output file, aborting Write.");
        return false;
    }
    auto handle = outfile.getOutHandle();

    const auto sample_rate = sample->getSampleRate();
    const auto num_channels = static_cast<unsigned>(sample->getNumChannels());
    const auto bytes_per_sample = sample->getBitDepth() / 8;
    unsigned byte_rate = sample_rate*num_channels*bytes_per_sample;

    handle->write("RIFF", 4);
    auto data = sample->getChannelData(0);
    const auto num_samples = static_cast<unsigned>(data.size());
    unsigned content_size = 36 + bytes_per_sample* num_samples*num_channels;

    BinaryStream::write<int>(handle, content_size);
    handle->write("WAVE", 4);

    /* write fmt  subchunk */
    handle->write("fmt ", 4);
    BinaryStream::write<int>(handle, 16); // SubChunk1Size
    BinaryStream::write<short>(handle, 1); // PCM Format
    BinaryStream::write<short>(handle, num_channels);
    BinaryStream::write<int>(handle, sample_rate);
    BinaryStream::write<int>(handle, byte_rate);
    BinaryStream::write<short>(handle, num_channels*bytes_per_sample); // block align
    BinaryStream::write<short>(handle, 8*bytes_per_sample); // bits/sample

    /* write data subchunk */
    handle->write("data", 4);
    BinaryStream::write<int>(handle, static_cast<int>(bytes_per_sample* num_samples*num_channels)); // bits/sample

    handle->write(reinterpret_cast<const char*>(&data[0]), data.size()*sizeof(short));

    return true;
}
